@caypo/canton-mcp 0.1.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/.turbo/turbo-build.log +14 -0
- package/.turbo/turbo-test.log +12 -0
- package/README.md +84 -0
- package/SPEC.md +93 -0
- package/dist/index.js +643 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
- package/src/index.ts +40 -0
- package/src/prompts/index.ts +207 -0
- package/src/tools/balance.ts +79 -0
- package/src/tools/checking.ts +75 -0
- package/src/tools/index.ts +60 -0
- package/src/tools/mpp.ts +98 -0
- package/src/tools/safeguards.ts +67 -0
- package/src/tools/stubs.ts +46 -0
- package/src/tools/traffic.ts +44 -0
- package/src/tools/types.ts +15 -0
- package/tsconfig.json +8 -0
- package/tsup.config.ts +12 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/tools/index.ts","../src/tools/balance.ts","../src/tools/checking.ts","../src/tools/mpp.ts","../src/tools/safeguards.ts","../src/tools/traffic.ts","../src/tools/stubs.ts","../src/prompts/index.ts"],"sourcesContent":["/**\n * @caypo/canton-mcp — MCP server for Canton Network agent.\n * 33 tools + 20 prompts for AI agent integration.\n *\n * Transport: stdio (standard for Claude Desktop MCP servers)\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { CantonAgent } from \"@caypo/canton-sdk\";\nimport { registerTools } from \"./tools/index.js\";\nimport { registerPrompts } from \"./prompts/index.js\";\n\nexport const CANTON_MCP_VERSION = \"0.1.0\";\n\nasync function main() {\n // 1. Create agent\n const agent = await CantonAgent.create({\n token: process.env.CANTON_JWT ?? \"\",\n });\n\n // 2. Create MCP server\n const server = new Server(\n { name: \"caypo\", version: CANTON_MCP_VERSION },\n { capabilities: { tools: {}, prompts: {} } },\n );\n\n // 3. Register tools and prompts\n registerTools(server, agent);\n registerPrompts(server);\n\n // 4. Connect via stdio\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n console.error(\"MCP server failed to start:\", err);\n process.exit(1);\n});\n","/**\n * Register all 33 tools on the MCP server.\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { CantonAgent } from \"@caypo/canton-sdk\";\nimport { balanceTools } from \"./balance.js\";\nimport { checkingTools } from \"./checking.js\";\nimport { mppTools } from \"./mpp.js\";\nimport { safeguardTools } from \"./safeguards.js\";\nimport { trafficTools } from \"./traffic.js\";\nimport { stubTools } from \"./stubs.js\";\nimport type { ToolDef } from \"./types.js\";\n\nexport function registerTools(server: Server, agent: CantonAgent): void {\n const allTools: ToolDef[] = [\n ...balanceTools(agent),\n ...checkingTools(agent),\n ...mppTools(agent),\n ...safeguardTools(agent),\n ...trafficTools(agent),\n ...stubTools(),\n ];\n\n const toolMap = new Map<string, ToolDef>();\n for (const tool of allTools) {\n toolMap.set(tool.name, tool);\n }\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: allTools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tool = toolMap.get(request.params.name);\n if (!tool) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${request.params.name}` }],\n isError: true,\n };\n }\n\n try {\n return await tool.handler((request.params.arguments ?? {}) as Record<string, unknown>);\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Error: ${(err as Error).message}` }],\n isError: true,\n };\n }\n });\n}\n","/**\n * Balance & Info tools (5): caypo_balance, caypo_address, caypo_history, caypo_positions, caypo_rates\n */\n\nimport type { CantonAgent } from \"@caypo/canton-sdk\";\nimport type { ToolDef } from \"./types.js\";\n\nexport function balanceTools(agent: CantonAgent): ToolDef[] {\n return [\n {\n name: \"caypo_balance\",\n description: \"Get USDCx checking account balance and holding count\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => {\n const bal = await agent.checking.balance();\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n available: bal.available,\n holdingCount: bal.holdingCount,\n currency: \"USDCx\",\n network: agent.wallet.network,\n }, null, 2),\n },\n ],\n };\n },\n },\n {\n name: \"caypo_address\",\n description: \"Get Canton party ID (address) and network info\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => ({\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n partyId: agent.wallet.address,\n network: agent.wallet.network,\n format: \"<DisplayName>::<hex-fingerprint>\",\n }, null, 2),\n },\n ],\n }),\n },\n {\n name: \"caypo_history\",\n description: \"Get recent transaction history\",\n inputSchema: {\n type: \"object\",\n properties: { limit: { type: \"number\", description: \"Max transactions to return\", default: 20 } },\n },\n handler: async (args) => {\n const history = await agent.checking.history({ limit: (args as { limit?: number }).limit });\n return {\n content: [{ type: \"text\", text: JSON.stringify(history, null, 2) }],\n };\n },\n },\n {\n name: \"caypo_positions\",\n description: \"View DeFi positions (Coming in Phase 3)\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => ({\n content: [{ type: \"text\", text: \"DeFi positions are not yet available. Coming in Phase 3 when Canton DeFi protocols launch.\" }],\n }),\n },\n {\n name: \"caypo_rates\",\n description: \"Get exchange rates and APYs (Coming in Phase 3)\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => ({\n content: [{ type: \"text\", text: \"Exchange rates and APYs are not yet available. Coming in Phase 3.\" }],\n }),\n },\n ];\n}\n","/**\n * Checking tools (3): caypo_send, caypo_receive, caypo_contacts\n */\n\nimport type { CantonAgent } from \"@caypo/canton-sdk\";\nimport type { ToolDef } from \"./types.js\";\n\nexport function checkingTools(agent: CantonAgent): ToolDef[] {\n return [\n {\n name: \"caypo_send\",\n description: \"Send USDCx to a recipient via TransferFactory_Transfer. Checks safeguards before sending.\",\n inputSchema: {\n type: \"object\",\n properties: {\n recipient: { type: \"string\", description: \"Recipient Canton party ID\" },\n amount: { type: \"string\", description: \"Amount of USDCx to send (string, e.g. '1.50')\" },\n memo: { type: \"string\", description: \"Optional memo\" },\n },\n required: [\"recipient\", \"amount\"],\n },\n handler: async (args) => {\n const { recipient, amount, memo } = args as { recipient: string; amount: string; memo?: string };\n const result = await agent.checking.send(recipient, amount, { memo });\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n status: \"success\",\n amount,\n recipient,\n updateId: result.updateId,\n completionOffset: result.completionOffset,\n commandId: result.commandId,\n }, null, 2),\n },\n ],\n };\n },\n },\n {\n name: \"caypo_receive\",\n description: \"Show party ID and deposit instructions for receiving USDCx\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => ({\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n partyId: agent.wallet.address,\n network: agent.wallet.network,\n instructions: \"Send USDCx to this party ID. The sender needs a TransferPreapproval or must use a 2-step TransferInstruction.\",\n }, null, 2),\n },\n ],\n }),\n },\n {\n name: \"caypo_contacts\",\n description: \"Manage contact list — list, add, or remove contacts\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: { type: \"string\", enum: [\"list\", \"add\", \"remove\"], default: \"list\" },\n name: { type: \"string\", description: \"Contact name\" },\n partyId: { type: \"string\", description: \"Contact party ID\" },\n },\n },\n handler: async () => ({\n content: [{ type: \"text\", text: \"Contact management coming soon. Use party IDs directly for now.\" }],\n }),\n },\n ];\n}\n","/**\n * MPP Payment tools (3): caypo_pay, caypo_pay_status, caypo_services\n */\n\nimport type { CantonAgent } from \"@caypo/canton-sdk\";\nimport type { ToolDef } from \"./types.js\";\n\nexport function mppTools(agent: CantonAgent): ToolDef[] {\n return [\n {\n name: \"caypo_pay\",\n description: \"Pay for an API call via MPP (HTTP 402 auto-handling). Fetches URL, handles payment if 402, returns response.\",\n inputSchema: {\n type: \"object\",\n properties: {\n url: { type: \"string\", description: \"URL to fetch\" },\n method: { type: \"string\", description: \"HTTP method\", default: \"GET\" },\n body: { type: \"string\", description: \"Request body (JSON string)\" },\n maxPrice: { type: \"string\", description: \"Maximum price willing to pay in USDCx\" },\n },\n required: [\"url\"],\n },\n handler: async (args) => {\n const { url, method, body, maxPrice } = args as {\n url: string; method?: string; body?: string; maxPrice?: string;\n };\n const result = await agent.mpp.pay(url, {\n method,\n body,\n maxPrice,\n headers: body ? { \"Content-Type\": \"application/json\" } : undefined,\n });\n const responseBody = await result.response.text();\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n status: result.response.status,\n paid: result.paid,\n receipt: result.receipt,\n body: responseBody.slice(0, 2000),\n }, null, 2),\n },\n ],\n };\n },\n },\n {\n name: \"caypo_pay_status\",\n description: \"Check payment status by Canton update ID\",\n inputSchema: {\n type: \"object\",\n properties: {\n updateId: { type: \"string\", description: \"Canton transaction update ID\" },\n },\n required: [\"updateId\"],\n },\n handler: async () => ({\n content: [{ type: \"text\", text: \"Payment status lookup requires gateway integration. Use the updateId with the Canton Ledger API directly.\" }],\n }),\n },\n {\n name: \"caypo_services\",\n description: \"List available MPP gateway services and pricing\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => ({\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n gateway: \"mpp.cayvox.io\",\n services: [\n { name: \"OpenAI\", path: \"/openai\", price: \"$0.001-$0.05\" },\n { name: \"Anthropic\", path: \"/anthropic\", price: \"$0.01\" },\n { name: \"fal.ai\", path: \"/fal\", price: \"$0.01-$0.10\" },\n { name: \"Firecrawl\", path: \"/firecrawl\", price: \"$0.005-$0.02\" },\n { name: \"Google Gemini\", path: \"/gemini\", price: \"$0.005-$0.02\" },\n { name: \"Groq\", path: \"/groq\", price: \"$0.001-$0.005\" },\n { name: \"Perplexity\", path: \"/perplexity\", price: \"$0.01\" },\n { name: \"Brave Search\", path: \"/brave\", price: \"$0.001-$0.005\" },\n { name: \"DeepSeek\", path: \"/deepseek\", price: \"$0.005\" },\n { name: \"Resend\", path: \"/resend\", price: \"$0.005\" },\n { name: \"Together AI\", path: \"/together\", price: \"$0.001-$0.02\" },\n { name: \"ElevenLabs\", path: \"/elevenlabs\", price: \"$0.02-$0.05\" },\n { name: \"OpenWeather\", path: \"/openweather\", price: \"$0.001\" },\n { name: \"Google Maps\", path: \"/googlemaps\", price: \"$0.005\" },\n { name: \"Judge0\", path: \"/judge0\", price: \"$0.002\" },\n { name: \"Reloadly\", path: \"/reloadly\", price: \"$0.01+\" },\n { name: \"Lob\", path: \"/lob\", price: \"$0.01-$0.50\" },\n ],\n }, null, 2),\n },\n ],\n }),\n },\n ];\n}\n","/**\n * Safeguard tools (3): caypo_safeguards, caypo_set_limit, caypo_lock\n */\n\nimport type { CantonAgent } from \"@caypo/canton-sdk\";\nimport type { ToolDef } from \"./types.js\";\n\nexport function safeguardTools(agent: CantonAgent): ToolDef[] {\n return [\n {\n name: \"caypo_safeguards\",\n description: \"View current safeguard settings: tx limit, daily limit, lock status, daily spending\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => {\n const s = agent.safeguards.settings();\n return {\n content: [{ type: \"text\", text: JSON.stringify(s, null, 2) }],\n };\n },\n },\n {\n name: \"caypo_set_limit\",\n description: \"Set per-transaction or daily spending limit\",\n inputSchema: {\n type: \"object\",\n properties: {\n type: { type: \"string\", enum: [\"tx\", \"daily\"], description: \"Limit type\" },\n amount: { type: \"string\", description: \"Limit amount in USDCx\" },\n },\n required: [\"type\", \"amount\"],\n },\n handler: async (args) => {\n const { type, amount } = args as { type: \"tx\" | \"daily\"; amount: string };\n if (type === \"tx\") {\n agent.safeguards.setTxLimit(amount);\n } else {\n agent.safeguards.setDailyLimit(amount);\n }\n return {\n content: [{ type: \"text\", text: `${type === \"tx\" ? \"Per-transaction\" : \"Daily\"} limit set to ${amount} USDCx` }],\n };\n },\n },\n {\n name: \"caypo_lock\",\n description: \"Lock or unlock the wallet. When locked, all transactions are rejected.\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: { type: \"string\", enum: [\"lock\", \"unlock\"], description: \"Action to perform\" },\n pin: { type: \"string\", description: \"PIN for lock/unlock\" },\n },\n required: [\"action\"],\n },\n handler: async (args) => {\n const { action, pin } = args as { action: \"lock\" | \"unlock\"; pin?: string };\n if (action === \"lock\") {\n agent.safeguards.lock(pin);\n return { content: [{ type: \"text\", text: \"Wallet locked. All transactions will be rejected until unlocked.\" }] };\n } else {\n agent.safeguards.unlock(pin ?? \"\");\n return { content: [{ type: \"text\", text: \"Wallet unlocked.\" }] };\n }\n },\n },\n ];\n}\n","/**\n * Traffic tools (2): caypo_traffic, caypo_purchase_traffic\n */\n\nimport type { CantonAgent } from \"@caypo/canton-sdk\";\nimport type { ToolDef } from \"./types.js\";\n\nexport function trafficTools(agent: CantonAgent): ToolDef[] {\n return [\n {\n name: \"caypo_traffic\",\n description: \"Check validator traffic balance. Canton uses traffic budgets, not gas fees.\",\n inputSchema: { type: \"object\", properties: {}, required: [] },\n handler: async () => {\n const bal = await agent.traffic.trafficBalance();\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n ...bal,\n note: \"Canton uses traffic budgets per validator, not per-transaction gas fees.\",\n }, null, 2),\n },\n ],\n };\n },\n },\n {\n name: \"caypo_purchase_traffic\",\n description: \"Purchase additional traffic by burning Canton Coin (CC). Coming soon.\",\n inputSchema: {\n type: \"object\",\n properties: {\n ccAmount: { type: \"string\", description: \"Amount of CC to burn\" },\n },\n required: [\"ccAmount\"],\n },\n handler: async () => ({\n content: [{ type: \"text\", text: \"Traffic purchase is not yet implemented. Requires validator admin API access.\" }],\n }),\n },\n ];\n}\n","/**\n * Stub tools for Phase 3/4 features.\n * savings (4), credit (3), exchange (2), investment (8), rewards (2) = 19 stubs\n */\n\nimport type { ToolDef } from \"./types.js\";\n\nfunction stub(name: string, description: string, phase: string): ToolDef {\n return {\n name,\n description: `${description} (Coming in ${phase})`,\n inputSchema: { type: \"object\", properties: {} },\n handler: async () => ({\n content: [{ type: \"text\", text: `${description} is not yet available. Coming in ${phase} when Canton DeFi protocols launch.` }],\n }),\n };\n}\n\nexport function stubTools(): ToolDef[] {\n return [\n // Savings (4)\n stub(\"caypo_save\", \"Deposit USDCx into savings for yield\", \"Phase 3\"),\n stub(\"caypo_withdraw\", \"Withdraw from savings to checking\", \"Phase 3\"),\n stub(\"caypo_rebalance_savings\", \"Rebalance savings across protocols\", \"Phase 3\"),\n stub(\"caypo_earnings\", \"View savings earnings and APY\", \"Phase 3\"),\n // Credit (3)\n stub(\"caypo_borrow\", \"Borrow USDCx against collateral\", \"Phase 3\"),\n stub(\"caypo_repay\", \"Repay borrowed amount\", \"Phase 3\"),\n stub(\"caypo_health\", \"Check credit health factor\", \"Phase 3\"),\n // Exchange (2)\n stub(\"caypo_exchange\", \"Exchange tokens on Canton DEX\", \"Phase 3\"),\n stub(\"caypo_quote\", \"Get exchange rate quote\", \"Phase 3\"),\n // Investment (8)\n stub(\"caypo_invest_buy\", \"Buy investment assets\", \"Phase 4\"),\n stub(\"caypo_invest_sell\", \"Sell investment assets\", \"Phase 4\"),\n stub(\"caypo_invest_earn\", \"Stake assets for yield\", \"Phase 4\"),\n stub(\"caypo_invest_unearn\", \"Unstake assets\", \"Phase 4\"),\n stub(\"caypo_invest_rebalance\", \"Rebalance investment portfolio\", \"Phase 4\"),\n stub(\"caypo_portfolio\", \"View investment portfolio\", \"Phase 4\"),\n stub(\"caypo_strategy_buy\", \"Execute investment strategy\", \"Phase 4\"),\n stub(\"caypo_auto_invest\", \"Configure auto-invest DCA\", \"Phase 4\"),\n // Rewards (2)\n stub(\"caypo_claim_rewards\", \"Claim Canton Coin mining rewards\", \"Phase 3\"),\n stub(\"caypo_reward_history\", \"View reward claim history\", \"Phase 3\"),\n ];\n}\n","/**\n * Register all 20 prompts on the MCP server.\n * 5 fully implemented, 15 stubs.\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\ninterface PromptDef {\n name: string;\n description: string;\n arguments?: Array<{ name: string; description: string; required?: boolean }>;\n handler: (args: Record<string, string>) => { messages: Array<{ role: string; content: { type: string; text: string } }> };\n}\n\nfunction stubPrompt(name: string, description: string): PromptDef {\n return {\n name,\n description,\n handler: () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Please provide a ${description.toLowerCase()}. Note: This prompt template will be enhanced in a future version.`,\n },\n },\n ],\n }),\n };\n}\n\nconst prompts: PromptDef[] = [\n // 5 fully implemented prompts\n {\n name: \"morning_briefing\",\n description: \"Daily financial briefing — balance, spending, traffic, alerts\",\n handler: () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Good morning! Please give me my daily Canton agent briefing:\n\n1. **Balance**: Call caypo_balance to get my current USDCx balance and holding count.\n2. **Spending**: Call caypo_safeguards to check my daily spending vs limits.\n3. **Traffic**: Call caypo_traffic to check validator traffic status.\n4. **Recent activity**: Call caypo_history with limit=5 to show recent transactions.\n\nFormat as a concise morning briefing with key numbers highlighted.`,\n },\n },\n ],\n }),\n },\n {\n name: \"financial_report\",\n description: \"Comprehensive financial report — all accounts, spending patterns, recommendations\",\n handler: () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Generate a comprehensive financial report for my Canton agent:\n\n1. Call caypo_balance for current balance\n2. Call caypo_safeguards for spending limits and daily usage\n3. Call caypo_history with limit=20 for recent transactions\n4. Call caypo_traffic for traffic status\n\nAnalyze the data and provide:\n- Total balance and holding efficiency (suggest merging if >5 UTXOs)\n- Daily spending rate vs limits\n- Traffic consumption trend\n- Recommendations for limit adjustments`,\n },\n },\n ],\n }),\n },\n {\n name: \"spending_analysis\",\n description: \"Analyze recent spending patterns and suggest optimizations\",\n handler: () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Analyze my spending patterns:\n\n1. Call caypo_history with limit=50\n2. Call caypo_safeguards for current limits\n3. Call caypo_balance for current balance\n\nThen:\n- Categorize spending (API calls, transfers, etc.)\n- Identify the most expensive API services\n- Suggest whether my safeguard limits are appropriate\n- Flag any unusual transaction patterns`,\n },\n },\n ],\n }),\n },\n {\n name: \"security_audit\",\n description: \"Security audit — check safeguards, wallet status, traffic health\",\n handler: () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Perform a security audit of my Canton agent:\n\n1. Call caypo_safeguards — are limits set appropriately?\n2. Call caypo_traffic — is traffic healthy?\n3. Call caypo_balance — any concerns about holding count?\n4. Call caypo_address — verify network\n\nCheck for:\n- Are safeguard limits reasonable? (tx limit should be < 10% of balance)\n- Is the wallet locked when it should be?\n- Are there too many UTXOs? (>10 = recommend merge)\n- Is traffic balance sufficient?\n- Any signs of unusual activity?`,\n },\n },\n ],\n }),\n },\n {\n name: \"onboarding\",\n description: \"New user onboarding — explain Canton agent features and guide setup\",\n handler: () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Welcome a new user to CAYPO — their Canton Network agent bank account. Explain:\n\n1. **What CAYPO is**: A bank account for AI agents on Canton Network. Privacy-preserving, institutional-grade.\n2. **Key features**: USDCx checking account, MPP auto-payments for APIs, safeguards, traffic management.\n3. **How to get started**:\n - Call caypo_address to show their party ID\n - Call caypo_balance to check initial balance\n - Call caypo_safeguards to review default limits\n - Call caypo_services to see available paid APIs\n4. **Important concepts**:\n - Canton uses party IDs, not addresses\n - USDCx is USDC-backed via Circle xReserve\n - Amounts are always strings (never floating point)\n - Traffic replaces gas (validator-level, not per-tx)\n5. **Safety**: Safeguards protect against overspending. Always set appropriate limits.`,\n },\n },\n ],\n }),\n },\n // 15 stub prompts\n stubPrompt(\"what_if\", \"What-if financial scenario analysis\"),\n stubPrompt(\"optimize_yield\", \"Yield optimization recommendations\"),\n stubPrompt(\"risk_assessment\", \"Risk assessment for current positions\"),\n stubPrompt(\"investment_thesis\", \"Investment thesis generation\"),\n stubPrompt(\"rebalance_plan\", \"Portfolio rebalance plan\"),\n stubPrompt(\"savings_strategy\", \"Savings strategy recommendations\"),\n stubPrompt(\"credit_health\", \"Credit health assessment\"),\n stubPrompt(\"traffic_report\", \"Detailed traffic consumption report\"),\n stubPrompt(\"market_overview\", \"Canton market overview\"),\n stubPrompt(\"portfolio_review\", \"Investment portfolio review\"),\n stubPrompt(\"defi_opportunities\", \"DeFi opportunities on Canton\"),\n stubPrompt(\"weekly_summary\", \"Weekly financial summary\"),\n stubPrompt(\"budget_plan\", \"Budget planning assistant\"),\n stubPrompt(\"tax_summary\", \"Transaction tax summary\"),\n stubPrompt(\"troubleshoot\", \"Troubleshoot Canton agent issues\"),\n];\n\nexport function registerPrompts(server: Server): void {\n const promptMap = new Map<string, PromptDef>();\n for (const p of prompts) {\n promptMap.set(p.name, p);\n }\n\n server.setRequestHandler(ListPromptsRequestSchema, async () => ({\n prompts: prompts.map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments,\n })),\n }));\n\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const prompt = promptMap.get(request.params.name);\n if (!prompt) {\n throw new Error(`Unknown prompt: ${request.params.name}`);\n }\n return prompt.handler((request.params.arguments ?? {}) as Record<string, string>);\n });\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@caypo/canton-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server connecting Canton Network to Claude Desktop, Cursor, and Windsurf — 33 tools, 20 prompts",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"canton",
|
|
7
|
+
"mcp",
|
|
8
|
+
"ai-agents",
|
|
9
|
+
"claude",
|
|
10
|
+
"cursor",
|
|
11
|
+
"windsurf",
|
|
12
|
+
"payments",
|
|
13
|
+
"usdcx",
|
|
14
|
+
"model-context-protocol"
|
|
15
|
+
],
|
|
16
|
+
"author": "Cayvox Labs <anil@cayvox.com>",
|
|
17
|
+
"homepage": "https://github.com/anilkaracay/Caypo/tree/main/packages/mcp",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/anilkaracay/Caypo.git",
|
|
21
|
+
"directory": "packages/mcp"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"bin": {
|
|
27
|
+
"caypo-mcp": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"require": "./dist/index.cjs"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
38
|
+
"@caypo/canton-sdk": "0.1.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"tsup": "^8.4.0",
|
|
42
|
+
"typescript": "^5.8.0",
|
|
43
|
+
"vitest": "^3.1.0"
|
|
44
|
+
},
|
|
45
|
+
"license": "(Apache-2.0 OR MIT)",
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsup",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"lint": "eslint src/",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"clean": "rm -rf dist"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @caypo/canton-mcp — MCP server for Canton Network agent.
|
|
3
|
+
* 33 tools + 20 prompts for AI agent integration.
|
|
4
|
+
*
|
|
5
|
+
* Transport: stdio (standard for Claude Desktop MCP servers)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import { CantonAgent } from "@caypo/canton-sdk";
|
|
11
|
+
import { registerTools } from "./tools/index.js";
|
|
12
|
+
import { registerPrompts } from "./prompts/index.js";
|
|
13
|
+
|
|
14
|
+
export const CANTON_MCP_VERSION = "0.1.0";
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
// 1. Create agent
|
|
18
|
+
const agent = await CantonAgent.create({
|
|
19
|
+
token: process.env.CANTON_JWT ?? "",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// 2. Create MCP server
|
|
23
|
+
const server = new Server(
|
|
24
|
+
{ name: "caypo", version: CANTON_MCP_VERSION },
|
|
25
|
+
{ capabilities: { tools: {}, prompts: {} } },
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// 3. Register tools and prompts
|
|
29
|
+
registerTools(server, agent);
|
|
30
|
+
registerPrompts(server);
|
|
31
|
+
|
|
32
|
+
// 4. Connect via stdio
|
|
33
|
+
const transport = new StdioServerTransport();
|
|
34
|
+
await server.connect(transport);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
main().catch((err) => {
|
|
38
|
+
console.error("MCP server failed to start:", err);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register all 20 prompts on the MCP server.
|
|
3
|
+
* 5 fully implemented, 15 stubs.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
7
|
+
import {
|
|
8
|
+
GetPromptRequestSchema,
|
|
9
|
+
ListPromptsRequestSchema,
|
|
10
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
+
|
|
12
|
+
interface PromptDef {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
arguments?: Array<{ name: string; description: string; required?: boolean }>;
|
|
16
|
+
handler: (args: Record<string, string>) => { messages: Array<{ role: string; content: { type: string; text: string } }> };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function stubPrompt(name: string, description: string): PromptDef {
|
|
20
|
+
return {
|
|
21
|
+
name,
|
|
22
|
+
description,
|
|
23
|
+
handler: () => ({
|
|
24
|
+
messages: [
|
|
25
|
+
{
|
|
26
|
+
role: "user",
|
|
27
|
+
content: {
|
|
28
|
+
type: "text",
|
|
29
|
+
text: `Please provide a ${description.toLowerCase()}. Note: This prompt template will be enhanced in a future version.`,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const prompts: PromptDef[] = [
|
|
38
|
+
// 5 fully implemented prompts
|
|
39
|
+
{
|
|
40
|
+
name: "morning_briefing",
|
|
41
|
+
description: "Daily financial briefing — balance, spending, traffic, alerts",
|
|
42
|
+
handler: () => ({
|
|
43
|
+
messages: [
|
|
44
|
+
{
|
|
45
|
+
role: "user",
|
|
46
|
+
content: {
|
|
47
|
+
type: "text",
|
|
48
|
+
text: `Good morning! Please give me my daily Canton agent briefing:
|
|
49
|
+
|
|
50
|
+
1. **Balance**: Call caypo_balance to get my current USDCx balance and holding count.
|
|
51
|
+
2. **Spending**: Call caypo_safeguards to check my daily spending vs limits.
|
|
52
|
+
3. **Traffic**: Call caypo_traffic to check validator traffic status.
|
|
53
|
+
4. **Recent activity**: Call caypo_history with limit=5 to show recent transactions.
|
|
54
|
+
|
|
55
|
+
Format as a concise morning briefing with key numbers highlighted.`,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
}),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "financial_report",
|
|
63
|
+
description: "Comprehensive financial report — all accounts, spending patterns, recommendations",
|
|
64
|
+
handler: () => ({
|
|
65
|
+
messages: [
|
|
66
|
+
{
|
|
67
|
+
role: "user",
|
|
68
|
+
content: {
|
|
69
|
+
type: "text",
|
|
70
|
+
text: `Generate a comprehensive financial report for my Canton agent:
|
|
71
|
+
|
|
72
|
+
1. Call caypo_balance for current balance
|
|
73
|
+
2. Call caypo_safeguards for spending limits and daily usage
|
|
74
|
+
3. Call caypo_history with limit=20 for recent transactions
|
|
75
|
+
4. Call caypo_traffic for traffic status
|
|
76
|
+
|
|
77
|
+
Analyze the data and provide:
|
|
78
|
+
- Total balance and holding efficiency (suggest merging if >5 UTXOs)
|
|
79
|
+
- Daily spending rate vs limits
|
|
80
|
+
- Traffic consumption trend
|
|
81
|
+
- Recommendations for limit adjustments`,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "spending_analysis",
|
|
89
|
+
description: "Analyze recent spending patterns and suggest optimizations",
|
|
90
|
+
handler: () => ({
|
|
91
|
+
messages: [
|
|
92
|
+
{
|
|
93
|
+
role: "user",
|
|
94
|
+
content: {
|
|
95
|
+
type: "text",
|
|
96
|
+
text: `Analyze my spending patterns:
|
|
97
|
+
|
|
98
|
+
1. Call caypo_history with limit=50
|
|
99
|
+
2. Call caypo_safeguards for current limits
|
|
100
|
+
3. Call caypo_balance for current balance
|
|
101
|
+
|
|
102
|
+
Then:
|
|
103
|
+
- Categorize spending (API calls, transfers, etc.)
|
|
104
|
+
- Identify the most expensive API services
|
|
105
|
+
- Suggest whether my safeguard limits are appropriate
|
|
106
|
+
- Flag any unusual transaction patterns`,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "security_audit",
|
|
114
|
+
description: "Security audit — check safeguards, wallet status, traffic health",
|
|
115
|
+
handler: () => ({
|
|
116
|
+
messages: [
|
|
117
|
+
{
|
|
118
|
+
role: "user",
|
|
119
|
+
content: {
|
|
120
|
+
type: "text",
|
|
121
|
+
text: `Perform a security audit of my Canton agent:
|
|
122
|
+
|
|
123
|
+
1. Call caypo_safeguards — are limits set appropriately?
|
|
124
|
+
2. Call caypo_traffic — is traffic healthy?
|
|
125
|
+
3. Call caypo_balance — any concerns about holding count?
|
|
126
|
+
4. Call caypo_address — verify network
|
|
127
|
+
|
|
128
|
+
Check for:
|
|
129
|
+
- Are safeguard limits reasonable? (tx limit should be < 10% of balance)
|
|
130
|
+
- Is the wallet locked when it should be?
|
|
131
|
+
- Are there too many UTXOs? (>10 = recommend merge)
|
|
132
|
+
- Is traffic balance sufficient?
|
|
133
|
+
- Any signs of unusual activity?`,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
}),
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "onboarding",
|
|
141
|
+
description: "New user onboarding — explain Canton agent features and guide setup",
|
|
142
|
+
handler: () => ({
|
|
143
|
+
messages: [
|
|
144
|
+
{
|
|
145
|
+
role: "user",
|
|
146
|
+
content: {
|
|
147
|
+
type: "text",
|
|
148
|
+
text: `Welcome a new user to CAYPO — their Canton Network agent bank account. Explain:
|
|
149
|
+
|
|
150
|
+
1. **What CAYPO is**: A bank account for AI agents on Canton Network. Privacy-preserving, institutional-grade.
|
|
151
|
+
2. **Key features**: USDCx checking account, MPP auto-payments for APIs, safeguards, traffic management.
|
|
152
|
+
3. **How to get started**:
|
|
153
|
+
- Call caypo_address to show their party ID
|
|
154
|
+
- Call caypo_balance to check initial balance
|
|
155
|
+
- Call caypo_safeguards to review default limits
|
|
156
|
+
- Call caypo_services to see available paid APIs
|
|
157
|
+
4. **Important concepts**:
|
|
158
|
+
- Canton uses party IDs, not addresses
|
|
159
|
+
- USDCx is USDC-backed via Circle xReserve
|
|
160
|
+
- Amounts are always strings (never floating point)
|
|
161
|
+
- Traffic replaces gas (validator-level, not per-tx)
|
|
162
|
+
5. **Safety**: Safeguards protect against overspending. Always set appropriate limits.`,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
}),
|
|
167
|
+
},
|
|
168
|
+
// 15 stub prompts
|
|
169
|
+
stubPrompt("what_if", "What-if financial scenario analysis"),
|
|
170
|
+
stubPrompt("optimize_yield", "Yield optimization recommendations"),
|
|
171
|
+
stubPrompt("risk_assessment", "Risk assessment for current positions"),
|
|
172
|
+
stubPrompt("investment_thesis", "Investment thesis generation"),
|
|
173
|
+
stubPrompt("rebalance_plan", "Portfolio rebalance plan"),
|
|
174
|
+
stubPrompt("savings_strategy", "Savings strategy recommendations"),
|
|
175
|
+
stubPrompt("credit_health", "Credit health assessment"),
|
|
176
|
+
stubPrompt("traffic_report", "Detailed traffic consumption report"),
|
|
177
|
+
stubPrompt("market_overview", "Canton market overview"),
|
|
178
|
+
stubPrompt("portfolio_review", "Investment portfolio review"),
|
|
179
|
+
stubPrompt("defi_opportunities", "DeFi opportunities on Canton"),
|
|
180
|
+
stubPrompt("weekly_summary", "Weekly financial summary"),
|
|
181
|
+
stubPrompt("budget_plan", "Budget planning assistant"),
|
|
182
|
+
stubPrompt("tax_summary", "Transaction tax summary"),
|
|
183
|
+
stubPrompt("troubleshoot", "Troubleshoot Canton agent issues"),
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
export function registerPrompts(server: Server): void {
|
|
187
|
+
const promptMap = new Map<string, PromptDef>();
|
|
188
|
+
for (const p of prompts) {
|
|
189
|
+
promptMap.set(p.name, p);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
|
193
|
+
prompts: prompts.map((p) => ({
|
|
194
|
+
name: p.name,
|
|
195
|
+
description: p.description,
|
|
196
|
+
arguments: p.arguments,
|
|
197
|
+
})),
|
|
198
|
+
}));
|
|
199
|
+
|
|
200
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
201
|
+
const prompt = promptMap.get(request.params.name);
|
|
202
|
+
if (!prompt) {
|
|
203
|
+
throw new Error(`Unknown prompt: ${request.params.name}`);
|
|
204
|
+
}
|
|
205
|
+
return prompt.handler((request.params.arguments ?? {}) as Record<string, string>);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Balance & Info tools (5): caypo_balance, caypo_address, caypo_history, caypo_positions, caypo_rates
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CantonAgent } from "@caypo/canton-sdk";
|
|
6
|
+
import type { ToolDef } from "./types.js";
|
|
7
|
+
|
|
8
|
+
export function balanceTools(agent: CantonAgent): ToolDef[] {
|
|
9
|
+
return [
|
|
10
|
+
{
|
|
11
|
+
name: "caypo_balance",
|
|
12
|
+
description: "Get USDCx checking account balance and holding count",
|
|
13
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
14
|
+
handler: async () => {
|
|
15
|
+
const bal = await agent.checking.balance();
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: "text",
|
|
20
|
+
text: JSON.stringify({
|
|
21
|
+
available: bal.available,
|
|
22
|
+
holdingCount: bal.holdingCount,
|
|
23
|
+
currency: "USDCx",
|
|
24
|
+
network: agent.wallet.network,
|
|
25
|
+
}, null, 2),
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "caypo_address",
|
|
33
|
+
description: "Get Canton party ID (address) and network info",
|
|
34
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
35
|
+
handler: async () => ({
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: JSON.stringify({
|
|
40
|
+
partyId: agent.wallet.address,
|
|
41
|
+
network: agent.wallet.network,
|
|
42
|
+
format: "<DisplayName>::<hex-fingerprint>",
|
|
43
|
+
}, null, 2),
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "caypo_history",
|
|
50
|
+
description: "Get recent transaction history",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: { limit: { type: "number", description: "Max transactions to return", default: 20 } },
|
|
54
|
+
},
|
|
55
|
+
handler: async (args) => {
|
|
56
|
+
const history = await agent.checking.history({ limit: (args as { limit?: number }).limit });
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: "text", text: JSON.stringify(history, null, 2) }],
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "caypo_positions",
|
|
64
|
+
description: "View DeFi positions (Coming in Phase 3)",
|
|
65
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
66
|
+
handler: async () => ({
|
|
67
|
+
content: [{ type: "text", text: "DeFi positions are not yet available. Coming in Phase 3 when Canton DeFi protocols launch." }],
|
|
68
|
+
}),
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "caypo_rates",
|
|
72
|
+
description: "Get exchange rates and APYs (Coming in Phase 3)",
|
|
73
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
74
|
+
handler: async () => ({
|
|
75
|
+
content: [{ type: "text", text: "Exchange rates and APYs are not yet available. Coming in Phase 3." }],
|
|
76
|
+
}),
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checking tools (3): caypo_send, caypo_receive, caypo_contacts
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CantonAgent } from "@caypo/canton-sdk";
|
|
6
|
+
import type { ToolDef } from "./types.js";
|
|
7
|
+
|
|
8
|
+
export function checkingTools(agent: CantonAgent): ToolDef[] {
|
|
9
|
+
return [
|
|
10
|
+
{
|
|
11
|
+
name: "caypo_send",
|
|
12
|
+
description: "Send USDCx to a recipient via TransferFactory_Transfer. Checks safeguards before sending.",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
recipient: { type: "string", description: "Recipient Canton party ID" },
|
|
17
|
+
amount: { type: "string", description: "Amount of USDCx to send (string, e.g. '1.50')" },
|
|
18
|
+
memo: { type: "string", description: "Optional memo" },
|
|
19
|
+
},
|
|
20
|
+
required: ["recipient", "amount"],
|
|
21
|
+
},
|
|
22
|
+
handler: async (args) => {
|
|
23
|
+
const { recipient, amount, memo } = args as { recipient: string; amount: string; memo?: string };
|
|
24
|
+
const result = await agent.checking.send(recipient, amount, { memo });
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
type: "text",
|
|
29
|
+
text: JSON.stringify({
|
|
30
|
+
status: "success",
|
|
31
|
+
amount,
|
|
32
|
+
recipient,
|
|
33
|
+
updateId: result.updateId,
|
|
34
|
+
completionOffset: result.completionOffset,
|
|
35
|
+
commandId: result.commandId,
|
|
36
|
+
}, null, 2),
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "caypo_receive",
|
|
44
|
+
description: "Show party ID and deposit instructions for receiving USDCx",
|
|
45
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
46
|
+
handler: async () => ({
|
|
47
|
+
content: [
|
|
48
|
+
{
|
|
49
|
+
type: "text",
|
|
50
|
+
text: JSON.stringify({
|
|
51
|
+
partyId: agent.wallet.address,
|
|
52
|
+
network: agent.wallet.network,
|
|
53
|
+
instructions: "Send USDCx to this party ID. The sender needs a TransferPreapproval or must use a 2-step TransferInstruction.",
|
|
54
|
+
}, null, 2),
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
}),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "caypo_contacts",
|
|
61
|
+
description: "Manage contact list — list, add, or remove contacts",
|
|
62
|
+
inputSchema: {
|
|
63
|
+
type: "object",
|
|
64
|
+
properties: {
|
|
65
|
+
action: { type: "string", enum: ["list", "add", "remove"], default: "list" },
|
|
66
|
+
name: { type: "string", description: "Contact name" },
|
|
67
|
+
partyId: { type: "string", description: "Contact party ID" },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
handler: async () => ({
|
|
71
|
+
content: [{ type: "text", text: "Contact management coming soon. Use party IDs directly for now." }],
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register all 33 tools on the MCP server.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
|
+
import {
|
|
7
|
+
CallToolRequestSchema,
|
|
8
|
+
ListToolsRequestSchema,
|
|
9
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
10
|
+
import type { CantonAgent } from "@caypo/canton-sdk";
|
|
11
|
+
import { balanceTools } from "./balance.js";
|
|
12
|
+
import { checkingTools } from "./checking.js";
|
|
13
|
+
import { mppTools } from "./mpp.js";
|
|
14
|
+
import { safeguardTools } from "./safeguards.js";
|
|
15
|
+
import { trafficTools } from "./traffic.js";
|
|
16
|
+
import { stubTools } from "./stubs.js";
|
|
17
|
+
import type { ToolDef } from "./types.js";
|
|
18
|
+
|
|
19
|
+
export function registerTools(server: Server, agent: CantonAgent): void {
|
|
20
|
+
const allTools: ToolDef[] = [
|
|
21
|
+
...balanceTools(agent),
|
|
22
|
+
...checkingTools(agent),
|
|
23
|
+
...mppTools(agent),
|
|
24
|
+
...safeguardTools(agent),
|
|
25
|
+
...trafficTools(agent),
|
|
26
|
+
...stubTools(),
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const toolMap = new Map<string, ToolDef>();
|
|
30
|
+
for (const tool of allTools) {
|
|
31
|
+
toolMap.set(tool.name, tool);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
35
|
+
tools: allTools.map((t) => ({
|
|
36
|
+
name: t.name,
|
|
37
|
+
description: t.description,
|
|
38
|
+
inputSchema: t.inputSchema,
|
|
39
|
+
})),
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
43
|
+
const tool = toolMap.get(request.params.name);
|
|
44
|
+
if (!tool) {
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }],
|
|
47
|
+
isError: true,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
return await tool.handler((request.params.arguments ?? {}) as Record<string, unknown>);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
return {
|
|
55
|
+
content: [{ type: "text", text: `Error: ${(err as Error).message}` }],
|
|
56
|
+
isError: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|