@ecadlabs/tezosx-mcp 1.0.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.
Files changed (51) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +335 -0
  3. package/dist/adapters/index.d.ts +37 -0
  4. package/dist/adapters/index.js +57 -0
  5. package/dist/adapters/node.d.ts +18 -0
  6. package/dist/adapters/node.js +35 -0
  7. package/dist/adapters/types.d.ts +52 -0
  8. package/dist/adapters/types.js +25 -0
  9. package/dist/adapters/worker.d.ts +35 -0
  10. package/dist/adapters/worker.js +50 -0
  11. package/dist/index.d.ts +8 -0
  12. package/dist/index.js +144 -0
  13. package/dist/server.d.ts +36 -0
  14. package/dist/server.js +80 -0
  15. package/dist/tools/create_x402_payment.d.ts +27 -0
  16. package/dist/tools/create_x402_payment.js +55 -0
  17. package/dist/tools/fetch_with_x402.d.ts +28 -0
  18. package/dist/tools/fetch_with_x402.js +143 -0
  19. package/dist/tools/get_address.d.ts +20 -0
  20. package/dist/tools/get_address.js +24 -0
  21. package/dist/tools/get_addresses.d.ts +22 -0
  22. package/dist/tools/get_addresses.js +32 -0
  23. package/dist/tools/get_balance.d.ts +22 -0
  24. package/dist/tools/get_balance.js +27 -0
  25. package/dist/tools/get_dashboard.d.ts +21 -0
  26. package/dist/tools/get_dashboard.js +29 -0
  27. package/dist/tools/get_limits.d.ts +22 -0
  28. package/dist/tools/get_limits.js +61 -0
  29. package/dist/tools/get_operation_history.d.ts +21 -0
  30. package/dist/tools/get_operation_history.js +58 -0
  31. package/dist/tools/index.d.ts +113 -0
  32. package/dist/tools/index.js +59 -0
  33. package/dist/tools/parse_x402_requirements.d.ts +23 -0
  34. package/dist/tools/parse_x402_requirements.js +66 -0
  35. package/dist/tools/reveal_account.d.ts +34 -0
  36. package/dist/tools/reveal_account.js +51 -0
  37. package/dist/tools/send_xtz.d.ts +32 -0
  38. package/dist/tools/send_xtz.js +86 -0
  39. package/dist/tools/x402/sign.d.ts +12 -0
  40. package/dist/tools/x402/sign.js +76 -0
  41. package/dist/tools/x402/types.d.ts +40 -0
  42. package/dist/tools/x402/types.js +16 -0
  43. package/dist/webserver.d.ts +1 -0
  44. package/dist/webserver.js +10 -0
  45. package/dist/worker.bundle.js +134265 -0
  46. package/dist/worker.d.ts +13 -0
  47. package/dist/worker.js +132 -0
  48. package/frontend/dist/assets/index-RtTL1nIl.js +257 -0
  49. package/frontend/dist/assets/index-mSsI3AqQ.css +1 -0
  50. package/frontend/dist/index.html +16 -0
  51. package/package.json +70 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Environment adapter interface for abstracting platform-specific operations.
3
+ * This allows the MCP server to run in both Node.js and Cloudflare Workers environments.
4
+ */
5
+ export interface EnvConfig {
6
+ MCP_TRANSPORT?: string;
7
+ SKIP_FRONTEND?: string;
8
+ WEB_PORT?: string;
9
+ PORT?: string;
10
+ TEZOS_NETWORK?: string;
11
+ SPENDING_PRIVATE_KEY?: string;
12
+ SPENDING_CONTRACT?: string;
13
+ }
14
+ export interface EnvironmentAdapter {
15
+ /**
16
+ * Get environment variable value
17
+ */
18
+ getEnv(key: keyof EnvConfig): string | undefined;
19
+ /**
20
+ * Check if we're running in a Workers environment
21
+ */
22
+ isWorker(): boolean;
23
+ /**
24
+ * Base64 encode a string (Buffer.from in Node, btoa in Workers)
25
+ */
26
+ base64Encode(data: string): string;
27
+ /**
28
+ * Base64 decode a string
29
+ */
30
+ base64Decode(data: string): string;
31
+ /**
32
+ * Log a message (stderr in Node, console.log in Workers)
33
+ */
34
+ log(message: string): void;
35
+ }
36
+ /**
37
+ * Static file serving configuration for HTTP mode
38
+ */
39
+ export interface StaticFileConfig {
40
+ /** Path to serve static files from (Node.js only) */
41
+ staticPath?: string;
42
+ /** Whether to use SPA fallback (serve index.html for unknown routes) */
43
+ spaFallback?: boolean;
44
+ }
45
+ /**
46
+ * Runtime environment type
47
+ */
48
+ export type RuntimeEnvironment = 'node' | 'worker';
49
+ /**
50
+ * Detect the current runtime environment
51
+ */
52
+ export declare function detectEnvironment(): RuntimeEnvironment;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Environment adapter interface for abstracting platform-specific operations.
3
+ * This allows the MCP server to run in both Node.js and Cloudflare Workers environments.
4
+ */
5
+ /**
6
+ * Detect the current runtime environment
7
+ */
8
+ export function detectEnvironment() {
9
+ // Check for Cloudflare Workers-specific globals
10
+ // @ts-ignore - caches is a Workers global
11
+ if (typeof globalThis.caches !== 'undefined' && typeof globalThis.caches.default !== 'undefined') {
12
+ return 'worker';
13
+ }
14
+ // Check for other Workers indicators
15
+ // @ts-ignore - WorkerGlobalScope is a Workers type
16
+ if (typeof WorkerGlobalScope !== 'undefined') {
17
+ return 'worker';
18
+ }
19
+ // Check for Node.js process
20
+ if (typeof process !== 'undefined' && process.versions?.node) {
21
+ return 'node';
22
+ }
23
+ // Default to worker if we can't determine (safer for bundled code)
24
+ return 'worker';
25
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Cloudflare Workers environment adapter
3
+ * Uses Web APIs and Worker bindings instead of Node.js filesystem/process
4
+ */
5
+ import type { EnvironmentAdapter, EnvConfig } from './types.js';
6
+ /**
7
+ * Cloudflare Worker environment bindings type
8
+ * These are passed to the fetch handler by Cloudflare
9
+ */
10
+ export interface WorkerEnv {
11
+ MCP_TRANSPORT?: string;
12
+ SKIP_FRONTEND?: string;
13
+ WEB_PORT?: string;
14
+ PORT?: string;
15
+ TEZOS_NETWORK?: string;
16
+ SPENDING_PRIVATE_KEY?: string;
17
+ SPENDING_CONTRACT?: string;
18
+ }
19
+ export declare class WorkerAdapter implements EnvironmentAdapter {
20
+ private env;
21
+ constructor(env?: WorkerEnv);
22
+ /**
23
+ * Update the environment bindings (called per-request with the env from fetch handler)
24
+ */
25
+ setEnv(env: WorkerEnv): void;
26
+ getEnv(key: keyof EnvConfig): string | undefined;
27
+ isWorker(): boolean;
28
+ base64Encode(data: string): string;
29
+ base64Decode(data: string): string;
30
+ log(message: string): void;
31
+ }
32
+ /**
33
+ * Create a Worker adapter instance
34
+ */
35
+ export declare function createWorkerAdapter(env?: WorkerEnv): WorkerAdapter;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Cloudflare Workers environment adapter
3
+ * Uses Web APIs and Worker bindings instead of Node.js filesystem/process
4
+ */
5
+ export class WorkerAdapter {
6
+ env;
7
+ constructor(env = {}) {
8
+ this.env = env;
9
+ }
10
+ /**
11
+ * Update the environment bindings (called per-request with the env from fetch handler)
12
+ */
13
+ setEnv(env) {
14
+ this.env = env;
15
+ }
16
+ getEnv(key) {
17
+ return this.env[key];
18
+ }
19
+ isWorker() {
20
+ return true;
21
+ }
22
+ base64Encode(data) {
23
+ // Use TextEncoder for proper UTF-8 handling
24
+ const encoder = new TextEncoder();
25
+ const bytes = encoder.encode(data);
26
+ let binary = '';
27
+ for (let i = 0; i < bytes.length; i++) {
28
+ binary += String.fromCharCode(bytes[i]);
29
+ }
30
+ return btoa(binary);
31
+ }
32
+ base64Decode(data) {
33
+ const binary = atob(data);
34
+ const bytes = new Uint8Array(binary.length);
35
+ for (let i = 0; i < binary.length; i++) {
36
+ bytes[i] = binary.charCodeAt(i);
37
+ }
38
+ const decoder = new TextDecoder();
39
+ return decoder.decode(bytes);
40
+ }
41
+ log(message) {
42
+ console.log(`[tezosx-mcp] ${message}`);
43
+ }
44
+ }
45
+ /**
46
+ * Create a Worker adapter instance
47
+ */
48
+ export function createWorkerAdapter(env) {
49
+ return new WorkerAdapter(env);
50
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ export declare const DEFAULT_WEB_PORT = "13205";
3
+ import { TezosToolkit } from "@taquito/taquito";
4
+ export type WalletConfig = {
5
+ Tezos: TezosToolkit;
6
+ spendingContract: string;
7
+ spendingAddress: string;
8
+ } | null;
package/dist/index.js ADDED
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ export const DEFAULT_WEB_PORT = '13205';
3
+ import { config } from 'dotenv';
4
+ // Taquito
5
+ import { InMemorySigner } from "@taquito/signer";
6
+ import { TezosToolkit } from "@taquito/taquito";
7
+ // MCP
8
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { createTools } from "./tools/index.js";
11
+ // MCP hosted
12
+ import express from 'express';
13
+ // Webserver
14
+ import { startWebServer } from "./webserver.js";
15
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
16
+ import { fileURLToPath } from "url";
17
+ import { join } from "path";
18
+ config({ quiet: true });
19
+ const __dirname = fileURLToPath(new URL(".", import.meta.url));
20
+ // Global error handlers
21
+ process.on('uncaughtException', (err) => {
22
+ console.error('[tezosx-mcp] Uncaught exception:', err);
23
+ });
24
+ process.on('unhandledRejection', (reason) => {
25
+ console.error('[tezosx-mcp] Unhandled rejection:', reason);
26
+ });
27
+ // Network configurations
28
+ const NETWORKS = {
29
+ mainnet: {
30
+ rpcUrl: 'https://mainnet.tezos.ecadinfra.com',
31
+ tzktApi: 'https://api.tzkt.io',
32
+ },
33
+ shadownet: {
34
+ rpcUrl: 'https://shadownet.tezos.ecadinfra.com',
35
+ tzktApi: 'https://api.shadownet.tzkt.io',
36
+ },
37
+ };
38
+ const log = (msg) => console.error(`[tezosx-mcp] ${msg}`);
39
+ const init = async () => {
40
+ log('Starting server...');
41
+ // Start web server for frontend (skip if SKIP_FRONTEND is set or if using HTTP transport)
42
+ const skipFrontend = process.env.SKIP_FRONTEND === 'true' || process.env.MCP_TRANSPORT === 'http';
43
+ if (!skipFrontend) {
44
+ const webPort = parseInt(process.env.WEB_PORT || DEFAULT_WEB_PORT, 10);
45
+ startWebServer(webPort);
46
+ log(`Frontend server started on port ${webPort}`);
47
+ }
48
+ const server = new McpServer({
49
+ name: "tezosx-mcp",
50
+ version: "1.0.0"
51
+ });
52
+ // Network configuration
53
+ const networkName = (process.env.TEZOS_NETWORK || 'mainnet');
54
+ const network = NETWORKS[networkName];
55
+ if (!network) {
56
+ throw new ReferenceError(`Invalid network: ${networkName}. Valid options: ${Object.keys(NETWORKS).join(', ')}`);
57
+ }
58
+ log(`Network: ${networkName}`);
59
+ // Taquito setup
60
+ const Tezos = new TezosToolkit(network.rpcUrl);
61
+ // Wallet configuration (optional - tools will guide user to configure if not set)
62
+ let walletConfig = null;
63
+ const privateKey = process.env.SPENDING_PRIVATE_KEY?.trim();
64
+ const spendingContract = process.env.SPENDING_CONTRACT?.trim();
65
+ if (privateKey && spendingContract) {
66
+ log('Configuring wallet...');
67
+ // Validate private key format
68
+ if (!privateKey.startsWith('edsk') && !privateKey.startsWith('spsk') && !privateKey.startsWith('p2sk')) {
69
+ log(`Warning: Invalid SPENDING_PRIVATE_KEY format. Must start with edsk, spsk, or p2sk. Wallet not configured.`);
70
+ }
71
+ else {
72
+ try {
73
+ const signer = await InMemorySigner.fromSecretKey(privateKey);
74
+ Tezos.setSignerProvider(signer);
75
+ const spendingAddress = await Tezos.signer.publicKeyHash();
76
+ walletConfig = { Tezos, spendingContract, spendingAddress };
77
+ log(`Wallet configured: ${spendingAddress}`);
78
+ }
79
+ catch (error) {
80
+ log(`Warning: Failed to initialize signer: ${error instanceof Error ? error.message : 'Unknown error'}. Wallet not configured.`);
81
+ }
82
+ }
83
+ }
84
+ else {
85
+ log('Wallet not configured (missing SPENDING_PRIVATE_KEY or SPENDING_CONTRACT)');
86
+ }
87
+ // Tools
88
+ log('Registering tools...');
89
+ const http = process.env.MCP_TRANSPORT === 'http';
90
+ const tools = createTools(walletConfig, network.tzktApi, http);
91
+ tools.forEach(tool => {
92
+ server.registerTool(tool.name, tool.config, tool.handler);
93
+ });
94
+ log(`Registered ${tools.length} tools`);
95
+ const transport = process.env.MCP_TRANSPORT || 'stdio';
96
+ log(`Transport: ${transport}`);
97
+ if (transport === 'http') {
98
+ const app = express();
99
+ app.use(express.json());
100
+ // Dashboard frontend (serve from frontend/dist)
101
+ const frontendPath = join(__dirname, "../frontend/dist");
102
+ app.use(express.static(frontendPath));
103
+ // MCP endpoint
104
+ app.post('/mcp', async (req, res) => {
105
+ log('Received MCP request');
106
+ const httpTransport = new StreamableHTTPServerTransport({
107
+ sessionIdGenerator: undefined,
108
+ enableJsonResponse: true
109
+ });
110
+ res.on('close', () => httpTransport.close());
111
+ await server.connect(httpTransport);
112
+ await httpTransport.handleRequest(req, res, req.body);
113
+ });
114
+ // SPA fallback - serve index.html for all non-API routes
115
+ app.get('/{*path}', (req, res) => {
116
+ res.sendFile(join(frontendPath, 'index.html'));
117
+ });
118
+ const port = process.env.PORT || 3004;
119
+ // Keep reference to http server and wait for it to start
120
+ await new Promise((resolve) => {
121
+ const httpServer = app.listen(port, () => {
122
+ log(`HTTP server listening on port ${port}`);
123
+ log(`MCP endpoint: http://localhost:${port}/mcp`);
124
+ resolve();
125
+ });
126
+ // Keep process alive
127
+ httpServer.on('error', (err) => {
128
+ log(`HTTP server error: ${err.message}`);
129
+ });
130
+ });
131
+ // Keep the process running
132
+ log('Server ready, waiting for requests...');
133
+ }
134
+ else {
135
+ log('Connecting stdio transport...');
136
+ const stdioTransport = new StdioServerTransport();
137
+ await server.connect(stdioTransport);
138
+ log('Stdio transport connected');
139
+ }
140
+ };
141
+ init().catch(err => {
142
+ console.error('[tezosx-mcp] Fatal error:', err);
143
+ process.exit(1);
144
+ });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Core MCP server setup - shared between Node.js and Workers environments
3
+ */
4
+ import { TezosToolkit } from "@taquito/taquito";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import type { EnvironmentAdapter } from "./adapters/index.js";
7
+ export type WalletConfig = {
8
+ Tezos: TezosToolkit;
9
+ spendingContract: string;
10
+ spendingAddress: string;
11
+ } | null;
12
+ declare const NETWORKS: {
13
+ readonly mainnet: {
14
+ readonly rpcUrl: "https://mainnet.tezos.ecadinfra.com";
15
+ readonly tzktApi: "https://api.tzkt.io";
16
+ };
17
+ readonly shadownet: {
18
+ readonly rpcUrl: "https://shadownet.tezos.ecadinfra.com";
19
+ readonly tzktApi: "https://api.shadownet.tzkt.io";
20
+ };
21
+ };
22
+ export type NetworkName = keyof typeof NETWORKS;
23
+ export type NetworkConfig = typeof NETWORKS[NetworkName];
24
+ export interface ServerConfig {
25
+ server: McpServer;
26
+ walletConfig: WalletConfig;
27
+ network: NetworkConfig;
28
+ networkName: NetworkName;
29
+ isHttp: boolean;
30
+ }
31
+ /**
32
+ * Initialize the MCP server with tools and wallet configuration
33
+ * This is the shared core that works in both Node.js and Workers
34
+ */
35
+ export declare function createMcpServer(adapter: EnvironmentAdapter): Promise<ServerConfig>;
36
+ export {};
package/dist/server.js ADDED
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Core MCP server setup - shared between Node.js and Workers environments
3
+ */
4
+ import { InMemorySigner } from "@taquito/signer";
5
+ import { TezosToolkit } from "@taquito/taquito";
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { createTools } from "./tools/index.js";
8
+ // Network configurations
9
+ const NETWORKS = {
10
+ mainnet: {
11
+ rpcUrl: 'https://mainnet.tezos.ecadinfra.com',
12
+ tzktApi: 'https://api.tzkt.io',
13
+ },
14
+ shadownet: {
15
+ rpcUrl: 'https://shadownet.tezos.ecadinfra.com',
16
+ tzktApi: 'https://api.shadownet.tzkt.io',
17
+ },
18
+ };
19
+ /**
20
+ * Initialize the MCP server with tools and wallet configuration
21
+ * This is the shared core that works in both Node.js and Workers
22
+ */
23
+ export async function createMcpServer(adapter) {
24
+ const log = (msg) => adapter.log(msg);
25
+ log('Initializing MCP server...');
26
+ const server = new McpServer({
27
+ name: "tezosx-mcp",
28
+ version: "1.0.0"
29
+ });
30
+ // Network configuration
31
+ const networkName = (adapter.getEnv('TEZOS_NETWORK') || 'mainnet');
32
+ const network = NETWORKS[networkName];
33
+ if (!network) {
34
+ throw new ReferenceError(`Invalid network: ${networkName}. Valid options: ${Object.keys(NETWORKS).join(', ')}`);
35
+ }
36
+ log(`Network: ${networkName}`);
37
+ // Taquito setup
38
+ const Tezos = new TezosToolkit(network.rpcUrl);
39
+ // Wallet configuration (optional - tools will guide user to configure if not set)
40
+ let walletConfig = null;
41
+ const privateKey = adapter.getEnv('SPENDING_PRIVATE_KEY')?.trim();
42
+ const spendingContract = adapter.getEnv('SPENDING_CONTRACT')?.trim();
43
+ if (privateKey && spendingContract) {
44
+ log('Configuring wallet...');
45
+ // Validate private key format
46
+ if (!privateKey.startsWith('edsk') && !privateKey.startsWith('spsk') && !privateKey.startsWith('p2sk')) {
47
+ log(`Warning: Invalid SPENDING_PRIVATE_KEY format. Must start with edsk, spsk, or p2sk. Wallet not configured.`);
48
+ }
49
+ else {
50
+ try {
51
+ const signer = await InMemorySigner.fromSecretKey(privateKey);
52
+ Tezos.setSignerProvider(signer);
53
+ const spendingAddress = await Tezos.signer.publicKeyHash();
54
+ walletConfig = { Tezos, spendingContract, spendingAddress };
55
+ log(`Wallet configured: ${spendingAddress}`);
56
+ }
57
+ catch (error) {
58
+ log(`Warning: Failed to initialize signer: ${error instanceof Error ? error.message : 'Unknown error'}. Wallet not configured.`);
59
+ }
60
+ }
61
+ }
62
+ else {
63
+ log('Wallet not configured (missing SPENDING_PRIVATE_KEY or SPENDING_CONTRACT)');
64
+ }
65
+ // Tools
66
+ log('Registering tools...');
67
+ const isHttp = adapter.getEnv('MCP_TRANSPORT') === 'http';
68
+ const tools = createTools(walletConfig, network.tzktApi, isHttp);
69
+ tools.forEach(tool => {
70
+ server.registerTool(tool.name, tool.config, tool.handler);
71
+ });
72
+ log(`Registered ${tools.length} tools`);
73
+ return {
74
+ server,
75
+ walletConfig,
76
+ network,
77
+ networkName,
78
+ isHttp
79
+ };
80
+ }
@@ -0,0 +1,27 @@
1
+ import { TezosToolkit } from "@taquito/taquito";
2
+ import z from "zod";
3
+ export declare const createCreateX402PaymentTool: (Tezos: TezosToolkit) => {
4
+ name: string;
5
+ config: {
6
+ title: string;
7
+ description: string;
8
+ inputSchema: z.ZodObject<{
9
+ network: z.ZodString;
10
+ asset: z.ZodString;
11
+ amount: z.ZodString;
12
+ recipient: z.ZodString;
13
+ }, z.z.core.$strip>;
14
+ annotations: {
15
+ readOnlyHint: boolean;
16
+ destructiveHint: boolean;
17
+ idempotentHint: boolean;
18
+ openWorldHint: boolean;
19
+ };
20
+ };
21
+ handler: (params: any) => Promise<{
22
+ content: {
23
+ type: "text";
24
+ text: string;
25
+ }[];
26
+ }>;
27
+ };
@@ -0,0 +1,55 @@
1
+ import z from "zod";
2
+ import { signX402Payment } from "./x402/sign.js";
3
+ export const createCreateX402PaymentTool = (Tezos) => ({
4
+ name: "tezos_create_x402_payment",
5
+ config: {
6
+ title: "Create x402 Payment",
7
+ description: "Creates a signed Tezos payment for x402 protocol. Builds and signs a transfer operation without broadcasting it, then packages it as a base64-encoded X-PAYMENT header value.",
8
+ inputSchema: z.object({
9
+ network: z.string().describe("The Tezos network (e.g., 'shadownet', 'mainnet')"),
10
+ asset: z.string().describe("The asset to pay with (e.g., 'XTZ')"),
11
+ amount: z.string().describe("The amount in mutez to send"),
12
+ recipient: z.string().describe("The recipient Tezos address (tz1...)")
13
+ }),
14
+ annotations: {
15
+ readOnlyHint: false,
16
+ destructiveHint: false,
17
+ idempotentHint: false,
18
+ openWorldHint: true,
19
+ }
20
+ },
21
+ handler: async (params) => {
22
+ const { network, asset, amount, recipient } = params;
23
+ // Validate asset type
24
+ if (asset !== "XTZ") {
25
+ throw new Error(`Unsupported asset: ${asset}. Only XTZ is supported.`);
26
+ }
27
+ const amountMutez = parseInt(amount, 10);
28
+ if (isNaN(amountMutez) || amountMutez <= 0) {
29
+ throw new Error(`Invalid amount: ${amount}. Must be a positive integer in mutez.`);
30
+ }
31
+ // Get source address from signer
32
+ const source = await Tezos.signer.publicKeyHash();
33
+ // Validate source has sufficient funds
34
+ const sourceBalance = await Tezos.tz.getBalance(source);
35
+ if (sourceBalance.toNumber() < amountMutez + 10000) { // Add buffer for fees
36
+ throw new Error(`Insufficient balance. ` +
37
+ `Required: ${amountMutez + 10000} mutez (including fees), ` +
38
+ `Available: ${sourceBalance.toNumber()} mutez`);
39
+ }
40
+ const signed = await signX402Payment(Tezos, {
41
+ network,
42
+ amount: amountMutez,
43
+ recipient,
44
+ });
45
+ return {
46
+ content: [{
47
+ type: "text",
48
+ text: JSON.stringify({
49
+ headerValue: signed.base64,
50
+ payload: signed.payload,
51
+ }, null, 2)
52
+ }]
53
+ };
54
+ }
55
+ });
@@ -0,0 +1,28 @@
1
+ import { TezosToolkit } from "@taquito/taquito";
2
+ import z from "zod";
3
+ export declare const createFetchWithX402Tool: (Tezos: TezosToolkit) => {
4
+ name: string;
5
+ config: {
6
+ title: string;
7
+ description: string;
8
+ inputSchema: z.ZodObject<{
9
+ url: z.ZodString;
10
+ maxAmountMutez: z.ZodString;
11
+ method: z.ZodOptional<z.ZodString>;
12
+ body: z.ZodOptional<z.ZodString>;
13
+ recipient: z.ZodOptional<z.ZodString>;
14
+ }, z.z.core.$strip>;
15
+ annotations: {
16
+ readOnlyHint: boolean;
17
+ destructiveHint: boolean;
18
+ idempotentHint: boolean;
19
+ openWorldHint: boolean;
20
+ };
21
+ };
22
+ handler: (params: any) => Promise<{
23
+ content: {
24
+ type: "text";
25
+ text: string;
26
+ }[];
27
+ }>;
28
+ };