diff --git a/eslint.config.js b/eslint.config.js index 0d0e305..be58e31 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -31,4 +31,9 @@ export default defineConfig([ }, { files: ["src/**/*.{js,mjs,cjs,ts}"], languageOptions: { globals: globals.node } }, tseslint.configs.recommended, + { + rules: { + "@typescript-eslint/no-explicit-any": 0, + } + } ]); diff --git a/package-lock.json b/package-lock.json index 60b15b5..9d47927 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenixd-mcp-server", - "version": "1.0.1", + "version": "1.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenixd-mcp-server", - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.11.2", @@ -92,9 +92,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -142,13 +142,16 @@ } }, "node_modules/@eslint/js": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", - "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", + "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -162,13 +165,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", - "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", + "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.14.0", "levn": "^0.4.1" }, "engines": { @@ -242,14 +245,15 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz", - "integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.0.tgz", + "integrity": "sha512-m//7RlINx1F3sz3KqwY1WWzVgTcYX52HYk4bJ1hkBXV3zccAEth+jRvG8DBRrdaQuRsPAJOx2MH3zaHNCKL7Zg==", "license": "MIT", "dependencies": { + "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", - "cross-spawn": "^7.0.3", + "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", @@ -315,9 +319,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", - "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", + "version": "22.15.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz", + "integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -580,7 +584,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -937,9 +940,9 @@ } }, "node_modules/eslint": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", - "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", + "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -947,14 +950,13 @@ "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.26.0", - "@eslint/plugin-kit": "^0.2.8", + "@eslint/js": "9.27.0", + "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", - "@modelcontextprotocol/sdk": "^1.8.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -978,8 +980,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "zod": "^3.24.2" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -1184,7 +1185,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -1221,7 +1221,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -1614,7 +1613,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -1972,7 +1970,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2428,7 +2425,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -2488,9 +2484,9 @@ } }, "node_modules/zod": { - "version": "3.24.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", - "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "version": "3.25.23", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.23.tgz", + "integrity": "sha512-Od2bdMosahjSrSgJtakrwjMDb1zM1A3VIHCPGveZt/3/wlrTWBya2lmEh2OYe4OIu8mPTmmr0gnLHIWQXdtWBg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 6e6499a..6ff4ef1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "phoenixd-mcp-server", - "version": "1.0.1", + "version": "1.0.2", "description": "Connect a phoenixd bitcoin lightning wallet to your LLM.", "keywords": [ "phoenixd", diff --git a/readme.md b/readme.md index 8515636..bf73551 100644 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ Add this to your `claude_desktop_config.json` file: ], "env": { "HTTP_PROTOCOL": "", // If not set http is the default value. - "HTTP_HOST": "", // 127.0.0.1 or your-domain.com + "HTTP_HOST": "", // If not set 127.0.0.1 is the default host. "HTTP_PORT": "", // If not set 9740 is the default port. "HTTP_PASSWORD": "" } diff --git a/src/index.ts b/src/index.ts index 16df403..2dda57c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,58 +3,37 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; -import { registerGetBalanceTool } from './tools/get_balance.js'; -import { registerGetNodeInfoTool } from './tools/get_node_info.js'; -import { registerListChannelsTool } from './tools/list_channels.js'; -import { registerCloseChannelTool } from './tools/close_channel.js'; -import { registerDecodeInvoiceTool } from './tools/decode_invoice.js'; -import { registerDecodeOfferTool } from './tools/decode_offer.js'; -import { registerCreateInvoiceTool } from './tools/create_invoice.js'; -import { registerPayInvoiceTool } from './tools/pay_invoice.js'; -import { registerCreateOfferTool } from './tools/create_offer.js'; -import { registerPayOfferTool } from './tools/pay_offer.js'; -import { registerPayLightningAddressTool } from './tools/pay_lightning_address.js'; -import { registerPayOnChainTool } from './tools/pay_on_chain.js'; -import { registerBumpFeeTool } from './tools/bump_fee.js'; -import { registerListIncomingPaymentsTool } from './tools/list_incoming_payments.js'; -import { registerGetIncomingPaymentTool } from './tools/get_incoming_payment.js'; -import { registerListOutgoingPaymentsTool } from './tools/list_outgoing_payments.js'; -import { registerGetOutgoingPaymentTool } from './tools/get_outgoing_payment.js'; +import { tools } from './tools/index.js'; const config = { httpPassword: process.env.HTTP_PASSWORD || '', httpPort: process.env.HTTP_PORT || '9740', - httpHost: process.env.HTTP_HOST || '', + httpHost: process.env.HTTP_HOST || '127.0.0.1', httpProtocol: process.env.HTTP_PROTOCOL || 'http', }; -if (!process.env.HTTP_PASSWORD || !process.env.HTTP_HOST) { - console.error('HTTP_PASSWORD and HTTP_HOST are required but not set in the environment variables.'); - process.exit(1); -} - const server = new McpServer({ name: 'phoenixd-mcp-server', version: '1.0.1', }); -await registerGetBalanceTool(server, config); -await registerGetNodeInfoTool(server, config); -await registerListChannelsTool(server, config); -await registerCloseChannelTool(server, config); -await registerDecodeInvoiceTool(server, config); -await registerDecodeOfferTool(server, config); -await registerCreateInvoiceTool(server, config); -await registerPayInvoiceTool(server, config); -await registerCreateOfferTool(server, config); -await registerPayOfferTool(server, config); -await registerPayLightningAddressTool(server, config); -await registerPayOnChainTool(server, config); -await registerBumpFeeTool(server, config); -await registerListIncomingPaymentsTool(server, config); -await registerGetIncomingPaymentTool(server, config); -await registerListOutgoingPaymentsTool(server, config); -await registerGetOutgoingPaymentTool(server, config); +await tools.registerGetBalanceTool(server, config); +await tools.registerGetNodeInfoTool(server, config); +await tools.registerListChannelsTool(server, config); +await tools.registerCloseChannelTool(server, config); +await tools.registerDecodeInvoiceTool(server, config); +await tools.registerDecodeOfferTool(server, config); +await tools.registerCreateInvoiceTool(server, config); +await tools.registerPayInvoiceTool(server, config); +await tools.registerCreateOfferTool(server, config); +await tools.registerPayOfferTool(server, config); +await tools.registerPayLightningAddressTool(server, config); +await tools.registerPayOnChainTool(server, config); +await tools.registerBumpFeeTool(server, config); +await tools.registerListIncomingPaymentsTool(server, config); +await tools.registerGetIncomingPaymentTool(server, config); +await tools.registerListOutgoingPaymentsTool(server, config); +await tools.registerGetOutgoingPaymentTool(server, config); const transport = new StdioServerTransport(); await server.connect(transport); diff --git a/src/tools/bump_fee.ts b/src/tools/bump_fee.ts index b43a371..14aba5e 100644 --- a/src/tools/bump_fee.ts +++ b/src/tools/bump_fee.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerBumpFeeTool( server: McpServer, @@ -13,6 +14,7 @@ export function registerBumpFeeTool( feerateSatByte: z.number().describe('The fee rate in satoshis per byte'), }, async ({ feerateSatByte }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const params = new URLSearchParams({ feerateSatByte: feerateSatByte.toString(), diff --git a/src/tools/close_channel.ts b/src/tools/close_channel.ts index f2b725a..630d024 100644 --- a/src/tools/close_channel.ts +++ b/src/tools/close_channel.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerCloseChannelTool( server: McpServer, @@ -15,6 +16,7 @@ export function registerCloseChannelTool( feerateSatByte: z.number().describe('The fee rate in satoshis per byte'), }, async ({ channelId, address, feerateSatByte }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const params = new URLSearchParams({ channelId, diff --git a/src/tools/create_invoice.ts b/src/tools/create_invoice.ts index 46e3fe1..a9d9221 100644 --- a/src/tools/create_invoice.ts +++ b/src/tools/create_invoice.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerCreateInvoiceTool( server: McpServer, @@ -18,6 +19,7 @@ export function registerCreateInvoiceTool( webhookUrl: z.string().optional().describe('A webhook url that will be notified when this specific payment has been received. '), }, async ({ description, amountSat, expirySeconds, externalId, webhookUrl }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const paramsObj: Record = { description, diff --git a/src/tools/create_offer.ts b/src/tools/create_offer.ts index fd001d5..66dd324 100644 --- a/src/tools/create_offer.ts +++ b/src/tools/create_offer.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerCreateOfferTool( server: McpServer, @@ -14,6 +15,7 @@ export function registerCreateOfferTool( amountSat: z.number().optional().describe('The amount requested by the offer, in satoshi. If not set, the offer can be paid by any amount'), }, async ({ description, amountSat }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const paramsObj: Record = {}; diff --git a/src/tools/decode_invoice.ts b/src/tools/decode_invoice.ts index 9be8024..0c31c71 100644 --- a/src/tools/decode_invoice.ts +++ b/src/tools/decode_invoice.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerDecodeInvoiceTool( server: McpServer, @@ -13,6 +14,7 @@ export function registerDecodeInvoiceTool( invoice: z.string().describe('The bolt11 invoice to decode'), }, async ({ invoice }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const params = new URLSearchParams({ invoice, diff --git a/src/tools/decode_offer.ts b/src/tools/decode_offer.ts index e6f7e73..b2d826d 100644 --- a/src/tools/decode_offer.ts +++ b/src/tools/decode_offer.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerDecodeOfferTool( server: McpServer, @@ -13,6 +14,7 @@ export function registerDecodeOfferTool( offer: z.string().describe('The bolt12 offer to decode'), }, async ({ offer }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const params = new URLSearchParams({ offer, diff --git a/src/tools/get_balance.ts b/src/tools/get_balance.ts index 14f7f68..31ff174 100644 --- a/src/tools/get_balance.ts +++ b/src/tools/get_balance.ts @@ -1,5 +1,6 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerGetBalanceTool( server: McpServer, @@ -9,6 +10,7 @@ export function registerGetBalanceTool( 'get-balance', 'Get the balance of the node', async () => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const data = await fetch(`${config.httpProtocol}://${config.httpHost}:${config.httpPort}/getbalance`, { method: 'GET', diff --git a/src/tools/get_incoming_payment.ts b/src/tools/get_incoming_payment.ts index d2910c4..db0c1a1 100644 --- a/src/tools/get_incoming_payment.ts +++ b/src/tools/get_incoming_payment.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerGetIncomingPaymentTool( server: McpServer, @@ -13,6 +14,7 @@ export function registerGetIncomingPaymentTool( paymentHash: z.string().describe('payment hash of the incoming payment'), }, async ({ paymentHash }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const data = await fetch(`${config.httpProtocol}://${config.httpHost}:${config.httpPort}/payments/incoming/${paymentHash}`, { diff --git a/src/tools/get_node_info.ts b/src/tools/get_node_info.ts index 0b34ddc..77a5908 100644 --- a/src/tools/get_node_info.ts +++ b/src/tools/get_node_info.ts @@ -1,5 +1,6 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerGetNodeInfoTool( server: McpServer, @@ -9,6 +10,7 @@ export function registerGetNodeInfoTool( 'get-node-info', 'Get the node info', async () => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const data = await fetch(`${config.httpProtocol}://${config.httpHost}:${config.httpPort}/getinfo`, { method: 'GET', diff --git a/src/tools/get_outgoing_payment.ts b/src/tools/get_outgoing_payment.ts index 17b29e9..0c21ce7 100644 --- a/src/tools/get_outgoing_payment.ts +++ b/src/tools/get_outgoing_payment.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerGetOutgoingPaymentTool( server: McpServer, @@ -13,6 +14,7 @@ export function registerGetOutgoingPaymentTool( paymentId: z.string().describe('payment hash of the outgoing payment'), }, async ({ paymentId }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const data = await fetch(`${config.httpProtocol}://${config.httpHost}:${config.httpPort}/payments/outgoing/${paymentId}`, { diff --git a/src/tools/index.ts b/src/tools/index.ts new file mode 100644 index 0000000..ba3951e --- /dev/null +++ b/src/tools/index.ts @@ -0,0 +1,37 @@ +import { registerGetBalanceTool } from './get_balance.js'; +import { registerGetNodeInfoTool } from './get_node_info.js'; +import { registerListChannelsTool } from './list_channels.js'; +import { registerCloseChannelTool } from './close_channel.js'; +import { registerDecodeInvoiceTool } from './decode_invoice.js'; +import { registerDecodeOfferTool } from './decode_offer.js'; +import { registerCreateInvoiceTool } from './create_invoice.js'; +import { registerPayInvoiceTool } from './pay_invoice.js'; +import { registerCreateOfferTool } from './create_offer.js'; +import { registerPayOfferTool } from './pay_offer.js'; +import { registerPayLightningAddressTool } from './pay_lightning_address.js'; +import { registerPayOnChainTool } from './pay_on_chain.js'; +import { registerBumpFeeTool } from './bump_fee.js'; +import { registerListIncomingPaymentsTool } from './list_incoming_payments.js'; +import { registerGetIncomingPaymentTool } from './get_incoming_payment.js'; +import { registerListOutgoingPaymentsTool } from './list_outgoing_payments.js'; +import { registerGetOutgoingPaymentTool } from './get_outgoing_payment.js'; + +export const tools = { + registerGetBalanceTool, + registerGetNodeInfoTool, + registerListChannelsTool, + registerCloseChannelTool, + registerDecodeInvoiceTool, + registerDecodeOfferTool, + registerCreateInvoiceTool, + registerPayInvoiceTool, + registerCreateOfferTool, + registerPayOfferTool, + registerPayLightningAddressTool, + registerPayOnChainTool, + registerBumpFeeTool, + registerListIncomingPaymentsTool, + registerGetIncomingPaymentTool, + registerListOutgoingPaymentsTool, + registerGetOutgoingPaymentTool, +}; diff --git a/src/tools/list_channels.ts b/src/tools/list_channels.ts index a352645..2462eea 100644 --- a/src/tools/list_channels.ts +++ b/src/tools/list_channels.ts @@ -1,5 +1,6 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerListChannelsTool( server: McpServer, @@ -9,6 +10,7 @@ export function registerListChannelsTool( 'list-channels', 'List the node channels', async () => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const data = await fetch(`${config.httpProtocol}://${config.httpHost}:${config.httpPort}/listchannels`, { method: 'GET', diff --git a/src/tools/list_incoming_payments.ts b/src/tools/list_incoming_payments.ts index 57c2f55..d2f4a60 100644 --- a/src/tools/list_incoming_payments.ts +++ b/src/tools/list_incoming_payments.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerListIncomingPaymentsTool( server: McpServer, @@ -18,6 +19,7 @@ export function registerListIncomingPaymentsTool( externalId: z.string().optional().describe('external id of the bolt11 invoice'), }, async ({ from, to, limit, offset, all, externalId }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const paramsObj: Record = { diff --git a/src/tools/list_outgoing_payments.ts b/src/tools/list_outgoing_payments.ts index 3282cab..2999398 100644 --- a/src/tools/list_outgoing_payments.ts +++ b/src/tools/list_outgoing_payments.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerListOutgoingPaymentsTool( server: McpServer, @@ -17,6 +18,7 @@ export function registerListOutgoingPaymentsTool( all: z.boolean().optional().describe('also return payments that have failed'), }, async ({ from, to, limit, offset, all }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const paramsObj: Record = { diff --git a/src/tools/pay_invoice.ts b/src/tools/pay_invoice.ts index 3a91f16..ce0c294 100644 --- a/src/tools/pay_invoice.ts +++ b/src/tools/pay_invoice.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerPayInvoiceTool( server: McpServer, @@ -14,6 +15,7 @@ export function registerPayInvoiceTool( invoice: z.string().describe('The bolt11 invoice to pay.'), }, async ({ amountSat, invoice }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const paramsObj: Record = { invoice, diff --git a/src/tools/pay_lightning_address.ts b/src/tools/pay_lightning_address.ts index 8983cf9..26b642a 100644 --- a/src/tools/pay_lightning_address.ts +++ b/src/tools/pay_lightning_address.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerPayLightningAddressTool( server: McpServer, @@ -15,6 +16,7 @@ export function registerPayLightningAddressTool( message: z.string().optional().describe('A message for the recipient.'), }, async ({ amountSat, address, message }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const paramsObj: Record = { address, diff --git a/src/tools/pay_offer.ts b/src/tools/pay_offer.ts index e2a13ae..9896c54 100644 --- a/src/tools/pay_offer.ts +++ b/src/tools/pay_offer.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerPayOfferTool( server: McpServer, @@ -15,6 +16,7 @@ export function registerPayOfferTool( message: z.string().optional().describe('A message for the recipient.'), }, async ({ amountSat, offer, message }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const paramsObj: Record = { offer, diff --git a/src/tools/pay_on_chain.ts b/src/tools/pay_on_chain.ts index 299d592..d818694 100644 --- a/src/tools/pay_on_chain.ts +++ b/src/tools/pay_on_chain.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { PhoenixdMcpConfig } from '../types'; +import { validateEnv } from '../utils/validate_env.js'; export function registerPayOnChainTool( server: McpServer, @@ -15,6 +16,7 @@ export function registerPayOnChainTool( feerateSatByte: z.number().describe('The fee rate in satoshis per byte'), }, async ({ amountSat, address, feerateSatByte }) => { + validateEnv(config); const credentials = btoa(`:${config.httpPassword}`); const params = new URLSearchParams({ amountSat: amountSat.toString(), diff --git a/src/utils/validate_env.ts b/src/utils/validate_env.ts new file mode 100644 index 0000000..86d1e5a --- /dev/null +++ b/src/utils/validate_env.ts @@ -0,0 +1,6 @@ +export function validateEnv(config: any) { + if (!config.httpPassword || !config.httpHost) { + console.error('HTTP_PASSWORD and HTTP_HOST are required but not set in the environment variables.'); + process.exit(1); + } +}