import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import axios from "axios";
import { x402Client, wrapAxiosWithPayment } from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { registerExactSvmScheme } from "@x402/svm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import { createKeyPairSignerFromBytes } from "@solana/kit";
import { base58 } from "@scure/base";
import { config } from "dotenv";
config();
const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`;
const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string;
const baseURL = process.env.RESOURCE_SERVER_URL || "http://localhost:4021";
const endpointPath = process.env.ENDPOINT_PATH || "/weather";
if (!evmPrivateKey && !svmPrivateKey) {
throw new Error("At least one of EVM_PRIVATE_KEY or SVM_PRIVATE_KEY must be provided");
}
/**
* Creates an axios client configured with x402 payment support for EVM and/or SVM.
*/
async function createClient() {
const client = new x402Client();
// Register EVM scheme if private key is provided
if (evmPrivateKey) {
const evmSigner = privateKeyToAccount(evmPrivateKey);
registerExactEvmScheme(client, { signer: evmSigner });
}
// Register SVM scheme if private key is provided
if (svmPrivateKey) {
const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey));
registerExactSvmScheme(client, { signer: svmSigner });
}
return wrapAxiosWithPayment(axios.create({ baseURL }), client);
}
async function main() {
const api = await createClient();
// Create an MCP server
const server = new McpServer({
name: "x402 MCP Client Demo",
version: "2.0.0",
});
// Add a tool that calls the paid API
server.tool(
"get-data-from-resource-server",
"Get data from the resource server (in this example, the weather)",
{},
async () => {
const res = await api.get(endpointPath);
return {
content: [{ type: "text", text: JSON.stringify(res.data) }],
};
},
);
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch(error => {
console.error(error);
process.exit(1);
});