Skip to main content
Glama
solution.ts7.29 kB
#!/usr/bin/env node import { jsonSchema } from 'ai'; import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, InitializeRequestSchema, Tool, } from "@modelcontextprotocol/sdk/types.js"; import { z } from "zod"; import { auth402_title, pay_and_get_402_protected_url, get402clientShape } from "./tools/402client.js"; import { zodToJsonSchema } from "zod-to-json-schema"; import { get_wallet_and_api_key_title, CreateAccountInput, login_with_otp, otpInput, login_with_otp_title, fund_my_wallet, get_PK,fund_my_wallet_title, get_wallet_and_api_key, getFundWalletShape, GetPKInput, get_PK_title } from './tools/auth.js'; import { send_money, getSendMoneyShape, send_money_title, request_payment_link, getCreatePLinkShape, request_payment_link_title, get_my_wallet_info, get_my_wallet_info_title, get_transaction_state, getGetTrxStateShape, get_transaction_state_title, get_wallet_history, getWalletHistoryShape, get_wallet_history_title, getGetWalletInfosShape } from './tools/payments.js'; import { serverJsonInfos } from './support/mcp.js'; // Tool definitions const tools: Tool[] = [ { name: "get_wallet_and_otp", description: get_wallet_and_api_key_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(CreateAccountInput))).jsonSchema, annotations: { title: get_wallet_and_api_key_title, readOnlyHint: true } }, { name: "login_with_otp", description: login_with_otp_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(otpInput))).jsonSchema, annotations: { title: login_with_otp_title, readOnlyHint: true } }, { name: "fund_my_wallet", description: fund_my_wallet_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(getFundWalletShape))).jsonSchema, annotations: { title: fund_my_wallet_title, readOnlyHint: true } }, { name: "get_private_key_of_wallet", description: get_PK_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(GetPKInput))).jsonSchema, annotations: { title: get_PK_title, readOnlyHint: true } }, { name: "send_money", description: send_money_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(getSendMoneyShape))).jsonSchema, annotations: { title: send_money_title, readOnlyHint: true } }, { name: "request_payment_link", description: request_payment_link_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(getCreatePLinkShape))).jsonSchema, annotations: { title: request_payment_link_title, readOnlyHint: true } }, { name: "get_wallet_info", description: get_my_wallet_info_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(getGetWalletInfosShape))).jsonSchema, annotations: { title: get_my_wallet_info_title, readOnlyHint: true } }, { name: "get_transaction_state", description: get_transaction_state_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(getGetTrxStateShape))).jsonSchema, annotations: { title: get_transaction_state_title, readOnlyHint: true } }, { name: "get_wallet_history", description: get_wallet_history_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(getWalletHistoryShape))).jsonSchema, annotations: { title: get_wallet_history_title, readOnlyHint: true } }, { name: "pay_and_get_402_protected_url", description: auth402_title, inputSchema: jsonSchema(zodToJsonSchema(z.object(get402clientShape))).jsonSchema, annotations: { title: 'Pay 402 link', destructiveHint: true, openWorldHint: true } } ]; // Main server setup const server = new Server(serverJsonInfos, { capabilities: { tools: {}, }, } ); // Initialize handler - REQUIRED for MCP protocol server.setRequestHandler(InitializeRequestSchema, async (request) => { return { protocolVersion: "2024-11-05", capabilities: { tools: {}, }, serverInfo: serverJsonInfos, }; }); // List tools handler server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; }); // Call tool handler server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { let result; switch (name) { case "get_wallet_and_otp": result = await get_wallet_and_api_key(args); break; case "login_with_otp": result = await login_with_otp(args); break; case "fund_my_wallet": result = await fund_my_wallet(args); break; case "get_private_key_of_wallet": result = await get_PK(args); break; case "send_money": result = await send_money(args); break; case "request_payment_link": result = await request_payment_link(args); break; case "get_wallet_info": result = await get_my_wallet_info(args); break; case "get_transaction_state": result = await get_transaction_state(args); break; case "get_wallet_history": result = await get_wallet_history(args); break; case "pay_and_get_402_protected_url": result = await pay_and_get_402_protected_url(args); break; default: throw new Error(`Unknown tool: ${name}`); } return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); export const configSchema = z.object({ API_KEY: z .string() .default('') .describe("API_KEY from P-Link.io [optional, you can get API_KEY using the MCP tools]"), }) // Export for Smithery export default function createServer({ config }: { config?: any }): Server { return server; } // Start server (for standalone mode) async function main() { try { const transport = new StdioServerTransport(); await server.connect(transport); console.error("P-Link MCP server running on stdio"); } catch (error) { console.error("Failed to start server:", error); process.exit(1); } } // Only run standalone if this is the main module (ES modules check) if (typeof process !== 'undefined' && process.argv[1] && process.argv[1].endsWith('index.js')) { main().catch((error) => { console.error("Server error:", error); process.exit(1); }); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/paracetamol951/P-Link-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server