@rapay/mcp-server 1.1.4

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.
@@ -0,0 +1,495 @@
1
+ /**
2
+ * Ra Pay MCP Server - Tool Handlers
3
+ *
4
+ * Subprocess isolation layer: MCP spawns CLI, never sees credentials.
5
+ * Credentials stored in file with restricted permissions (~/.rapay/config.toml, mode 0600).
6
+ * Only CLI accesses them. Note: File storage used for Windows/MSYS2 compatibility (v1.3.0+).
7
+ *
8
+ * @see MCP-SERVER-PLAN.md - Security Requirements
9
+ */
10
+ import spawn from "cross-spawn";
11
+ import { sanitizeError, sanitizeJsonResponse } from "./sanitize.js";
12
+ import { writeAuditLog, createAuditEntry } from "./audit.js";
13
+ /**
14
+ * CLI executable path - can be overridden via environment variable
15
+ * Security: Only allow absolute paths or "ra" (resolved via PATH)
16
+ */
17
+ const CLI_PATH = (() => {
18
+ const envPath = process.env.RAPAY_CLI_PATH;
19
+ if (!envPath)
20
+ return "ra";
21
+ // Security: Only allow absolute paths to prevent path traversal
22
+ // On Windows, absolute paths start with drive letter (C:\) or UNC (\\)
23
+ // On Unix, absolute paths start with /
24
+ const isAbsolute = envPath.startsWith("/") ||
25
+ /^[A-Za-z]:[/\\]/.test(envPath) ||
26
+ envPath.startsWith("\\\\");
27
+ if (!isAbsolute) {
28
+ console.error(`[SECURITY] RAPAY_CLI_PATH must be absolute path, got: ${envPath}`);
29
+ return "ra"; // Fall back to PATH resolution
30
+ }
31
+ return envPath;
32
+ })();
33
+ /**
34
+ * Maximum output size in bytes (1MB)
35
+ * Prevents memory exhaustion from malicious or runaway CLI output
36
+ */
37
+ const MAX_OUTPUT_SIZE = 1024 * 1024; // 1MB
38
+ const RATE_LIMITS = {
39
+ ra_send: { windowMs: 60000, maxCalls: 1 },
40
+ ra_subscribe: { windowMs: 60000, maxCalls: 1 },
41
+ ra_refund: { windowMs: 60000, maxCalls: 5 },
42
+ ra_balance: { windowMs: 60000, maxCalls: 10 },
43
+ ra_history: { windowMs: 60000, maxCalls: 10 },
44
+ ra_whoami: { windowMs: 60000, maxCalls: 20 },
45
+ };
46
+ /**
47
+ * In-memory rate limiter
48
+ * Per MCP server instance (each Claude Desktop has its own limits)
49
+ */
50
+ class RateLimiter {
51
+ calls = new Map();
52
+ isAllowed(toolName) {
53
+ const config = RATE_LIMITS[toolName];
54
+ if (!config)
55
+ return true; // Unknown tools pass through
56
+ const now = Date.now();
57
+ const windowStart = now - config.windowMs;
58
+ // Get existing calls for this tool
59
+ const toolCalls = this.calls.get(toolName) || [];
60
+ // Filter to calls within window
61
+ const recentCalls = toolCalls.filter((t) => t > windowStart);
62
+ if (recentCalls.length >= config.maxCalls) {
63
+ return false;
64
+ }
65
+ // Record this call
66
+ recentCalls.push(now);
67
+ this.calls.set(toolName, recentCalls);
68
+ return true;
69
+ }
70
+ getRetryAfter(toolName) {
71
+ const config = RATE_LIMITS[toolName];
72
+ if (!config)
73
+ return 0;
74
+ const toolCalls = this.calls.get(toolName) || [];
75
+ if (toolCalls.length === 0)
76
+ return 0;
77
+ const oldestCall = Math.min(...toolCalls);
78
+ const retryAfter = Math.ceil((oldestCall + config.windowMs - Date.now()) / 1000);
79
+ return Math.max(0, retryAfter);
80
+ }
81
+ }
82
+ const rateLimiter = new RateLimiter();
83
+ /**
84
+ * Input validation errors
85
+ */
86
+ class ValidationError extends Error {
87
+ constructor(message) {
88
+ super(message);
89
+ this.name = "ValidationError";
90
+ }
91
+ }
92
+ /**
93
+ * Validate ra_send arguments (defense-in-depth)
94
+ * MCP SDK validates schema, this is additional layer
95
+ */
96
+ function validateSendArgs(args) {
97
+ // Amount validation
98
+ if (typeof args.amount !== "number" || !Number.isFinite(args.amount)) {
99
+ throw new ValidationError("Amount must be a valid number");
100
+ }
101
+ if (args.amount < 100) {
102
+ throw new ValidationError("Minimum amount is 100 cents ($1.00)");
103
+ }
104
+ if (args.amount > 100000000) {
105
+ throw new ValidationError("Maximum amount is $1,000,000");
106
+ }
107
+ if (!Number.isInteger(args.amount)) {
108
+ throw new ValidationError("Amount must be a whole number of cents");
109
+ }
110
+ // Recipient ID validation
111
+ if (typeof args.recipient_id !== "string") {
112
+ throw new ValidationError("Recipient ID must be a string");
113
+ }
114
+ if (!/^acct_[a-zA-Z0-9]+$/.test(args.recipient_id)) {
115
+ throw new ValidationError("Invalid recipient ID format (expected acct_xxx)");
116
+ }
117
+ // Business purpose validation
118
+ if (typeof args.business_purpose !== "string") {
119
+ throw new ValidationError("Business purpose must be a string");
120
+ }
121
+ if (args.business_purpose.length < 10) {
122
+ throw new ValidationError("Business purpose must be at least 10 characters");
123
+ }
124
+ if (args.business_purpose.length > 200) {
125
+ throw new ValidationError("Business purpose must be at most 200 characters");
126
+ }
127
+ }
128
+ /**
129
+ * Validate ra_subscribe arguments
130
+ */
131
+ function validateSubscribeArgs(args) {
132
+ // Price ID validation
133
+ if (typeof args.price_id !== "string") {
134
+ throw new ValidationError("Price ID must be a string");
135
+ }
136
+ if (!/^price_[a-zA-Z0-9]+$/.test(args.price_id)) {
137
+ throw new ValidationError("Invalid price ID format (expected price_xxx)");
138
+ }
139
+ // Email validation (basic check, Stripe validates further)
140
+ if (typeof args.customer_email !== "string") {
141
+ throw new ValidationError("Customer email must be a string");
142
+ }
143
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(args.customer_email)) {
144
+ throw new ValidationError("Invalid email format");
145
+ }
146
+ if (args.customer_email.length > 254) {
147
+ throw new ValidationError("Email address too long");
148
+ }
149
+ }
150
+ /**
151
+ * Validate ra_history arguments
152
+ */
153
+ function validateHistoryArgs(args) {
154
+ if (args.limit !== undefined) {
155
+ if (typeof args.limit !== "number" || !Number.isFinite(args.limit)) {
156
+ throw new ValidationError("Limit must be a valid number");
157
+ }
158
+ if (!Number.isInteger(args.limit)) {
159
+ throw new ValidationError("Limit must be a whole number");
160
+ }
161
+ if (args.limit < 1) {
162
+ throw new ValidationError("Limit must be at least 1");
163
+ }
164
+ if (args.limit > 100) {
165
+ throw new ValidationError("Limit must be at most 100");
166
+ }
167
+ }
168
+ }
169
+ /**
170
+ * Execute a tool and return the result
171
+ *
172
+ * @param toolName - Name of the MCP tool to execute
173
+ * @param args - Tool arguments
174
+ * @returns Sanitized CLI output or error
175
+ */
176
+ export async function handleToolCall(toolName, args) {
177
+ const startTime = Date.now();
178
+ // Check rate limit
179
+ if (!rateLimiter.isAllowed(toolName)) {
180
+ const retryAfter = rateLimiter.getRetryAfter(toolName);
181
+ const error = {
182
+ error: "rate_limit_exceeded",
183
+ code: "RATE_LIMIT_EXCEEDED",
184
+ message: `Too many requests. Please wait ${retryAfter} seconds.`,
185
+ retry_after_seconds: retryAfter,
186
+ retryable: false,
187
+ };
188
+ // Log rate limit to audit
189
+ const auditEntry = createAuditEntry(toolName, args, startTime, "rate_limited", { code: "RATE_LIMIT_EXCEEDED", message: error.message });
190
+ await writeAuditLog(auditEntry);
191
+ return JSON.stringify(error, null, 2);
192
+ }
193
+ try {
194
+ let result;
195
+ switch (toolName) {
196
+ case "ra_send":
197
+ result = await executeSend(args);
198
+ break;
199
+ case "ra_subscribe":
200
+ result = await executeSubscribe(args);
201
+ break;
202
+ case "ra_refund":
203
+ result = await executeRefund();
204
+ break;
205
+ case "ra_balance":
206
+ result = await executeBalance();
207
+ break;
208
+ case "ra_history":
209
+ result = await executeHistory(args);
210
+ break;
211
+ case "ra_whoami":
212
+ result = await executeWhoami();
213
+ break;
214
+ default:
215
+ throw new Error(`Unknown tool: ${toolName}`);
216
+ }
217
+ // Log successful execution to audit
218
+ const auditEntry = createAuditEntry(toolName, args, startTime, "success");
219
+ await writeAuditLog(auditEntry);
220
+ return result;
221
+ }
222
+ catch (error) {
223
+ // Parse error for structured response
224
+ const errorInfo = parseCliError(error);
225
+ // Log error to audit
226
+ const auditEntry = createAuditEntry(toolName, args, startTime, "error", { code: errorInfo.code, message: errorInfo.message });
227
+ await writeAuditLog(auditEntry);
228
+ return JSON.stringify(errorInfo, null, 2);
229
+ }
230
+ }
231
+ /**
232
+ * Parse CLI error into structured response
233
+ */
234
+ function parseCliError(error) {
235
+ const message = error instanceof Error ? error.message : String(error);
236
+ // Input validation error (from our defense-in-depth validation)
237
+ if (error instanceof ValidationError) {
238
+ return {
239
+ error: "validation_error",
240
+ code: "VALIDATION_ERROR",
241
+ message: message,
242
+ retryable: false,
243
+ };
244
+ }
245
+ // CLI not found
246
+ if (message.includes("ENOENT") || message.includes("not found")) {
247
+ return {
248
+ error: "cli_not_found",
249
+ code: "CLI_NOT_FOUND",
250
+ message: "Ra Pay CLI not found. Please install it first: https://rapay.ai/docs/install",
251
+ retryable: false,
252
+ };
253
+ }
254
+ // ToS not accepted
255
+ if (message.includes("TOS_ACCEPTANCE_REQUIRED") || message.includes("accept-tos")) {
256
+ return {
257
+ error: "tos_required",
258
+ code: "TOS_ACCEPTANCE_REQUIRED",
259
+ message: "Terms of Service must be accepted. Run 'ra accept-tos' first.",
260
+ retryable: false,
261
+ };
262
+ }
263
+ // Account not linked
264
+ if (message.includes("not linked") || message.includes("link-bank")) {
265
+ return {
266
+ error: "account_not_linked",
267
+ code: "ACCOUNT_NOT_LINKED",
268
+ message: "Stripe account not linked. Run 'ra link-bank' first.",
269
+ retryable: false,
270
+ };
271
+ }
272
+ // Session expired or invalid (from server-side session management)
273
+ // Tightened 401 regex to avoid false positives (e.g., matching "401 Main St")
274
+ const is401Error = /(?:status|code|http)[^0-9]{0,10}401/i.test(message) ||
275
+ /401[^a-z]{0,10}(?:unauthorized|unauthenticated)/i.test(message);
276
+ if (message.includes("session expired") || message.includes("SESSION_EXPIRED") || message.includes("session invalid") || is401Error) {
277
+ return {
278
+ error: "session_expired",
279
+ code: "SESSION_EXPIRED",
280
+ message: "Session expired. Run 'ra link-bank' to re-authenticate.",
281
+ retryable: false,
282
+ };
283
+ }
284
+ // Velocity limit (backend limit)
285
+ if (message.includes("velocity") || message.includes("daily limit")) {
286
+ return {
287
+ error: "velocity_exceeded",
288
+ code: "VELOCITY_EXCEEDED",
289
+ message: "Daily transaction limit exceeded for your account tier.",
290
+ retryable: false,
291
+ };
292
+ }
293
+ // Timeout
294
+ if (message.includes("timed out") || message.includes("timeout")) {
295
+ return {
296
+ error: "timeout",
297
+ code: "TIMEOUT",
298
+ message: "Request timed out. Please try again.",
299
+ retryable: true,
300
+ };
301
+ }
302
+ // Network error
303
+ if (message.includes("network") || message.includes("ECONNREFUSED") || message.includes("ETIMEDOUT")) {
304
+ return {
305
+ error: "network_error",
306
+ code: "NETWORK_ERROR",
307
+ message: "Network error. Please check your connection and try again.",
308
+ retryable: true,
309
+ };
310
+ }
311
+ // Generic error
312
+ return {
313
+ error: "execution_failed",
314
+ code: "EXECUTION_FAILED",
315
+ message: sanitizeError(message),
316
+ retryable: false,
317
+ };
318
+ }
319
+ /**
320
+ * Execute Ra Pay CLI command as subprocess
321
+ * CLI inherits environment (credentials in keyring)
322
+ * MCP server never sees credentials directly
323
+ *
324
+ * Security measures:
325
+ * - Output size limited to MAX_OUTPUT_SIZE (1MB)
326
+ * - Timeout enforced (default 30s)
327
+ * - stderr sanitized and logged for debugging
328
+ *
329
+ * @param args - CLI arguments
330
+ * @param timeoutMs - Timeout in milliseconds (default: 30s)
331
+ * @returns Sanitized stdout
332
+ */
333
+ async function executeCliCommand(args, timeoutMs = 30000) {
334
+ return new Promise((resolve, reject) => {
335
+ const child = spawn(CLI_PATH, args, {
336
+ stdio: ["pipe", "pipe", "pipe"],
337
+ env: { ...process.env }, // Inherit environment for keyring access
338
+ // cross-spawn handles Windows .cmd wrappers automatically
339
+ });
340
+ let stdout = "";
341
+ let stderr = "";
342
+ let outputTruncated = false;
343
+ // Set timeout
344
+ const timeout = setTimeout(() => {
345
+ child.kill("SIGTERM");
346
+ reject(new Error("Command timed out"));
347
+ }, timeoutMs);
348
+ child.stdout?.on("data", (data) => {
349
+ const chunk = data.toString();
350
+ if (stdout.length + chunk.length > MAX_OUTPUT_SIZE) {
351
+ // Truncate to prevent memory exhaustion
352
+ stdout += chunk.substring(0, MAX_OUTPUT_SIZE - stdout.length);
353
+ outputTruncated = true;
354
+ child.kill("SIGTERM"); // Stop runaway process
355
+ }
356
+ else {
357
+ stdout += chunk;
358
+ }
359
+ });
360
+ child.stderr?.on("data", (data) => {
361
+ const chunk = data.toString();
362
+ // Cap stderr collection at 10KB (for error messages only)
363
+ if (stderr.length < 10240) {
364
+ stderr += chunk.substring(0, 10240 - stderr.length);
365
+ }
366
+ });
367
+ child.on("close", (code) => {
368
+ clearTimeout(timeout);
369
+ // Log stderr for debugging (sanitized, truncated)
370
+ if (stderr.length > 0) {
371
+ const sanitizedStderr = sanitizeError(stderr).substring(0, 500);
372
+ console.error(`[CLI_STDERR] ${sanitizedStderr}`);
373
+ }
374
+ if (outputTruncated) {
375
+ reject(new Error("Output exceeded 1MB limit and was truncated"));
376
+ return;
377
+ }
378
+ if (code === 0) {
379
+ // Sanitize successful output
380
+ resolve(sanitizeJsonResponse(stdout));
381
+ }
382
+ else {
383
+ // Sanitize error output
384
+ const errorMsg = stderr || `Command failed with code ${code}`;
385
+ reject(new Error(sanitizeError(errorMsg)));
386
+ }
387
+ });
388
+ child.on("error", (error) => {
389
+ clearTimeout(timeout);
390
+ // Log spawn errors for debugging
391
+ const errorType = error.message.includes("ENOENT") ? "CLI_NOT_FOUND" : "CLI_SPAWN_ERROR";
392
+ console.error(`[${errorType}] ${sanitizeError(error.message)}`);
393
+ reject(new Error(sanitizeError(error.message)));
394
+ });
395
+ });
396
+ }
397
+ /**
398
+ * Execute ra send command
399
+ * CLI handles: validation, confirmation, nonce generation, API call
400
+ *
401
+ * Two-step flow for fee disclosure compliance:
402
+ * 1. First call (user_confirmed=false): Returns fee preview, no payment executed
403
+ * 2. Second call (user_confirmed=true): Executes payment after user approves fee
404
+ */
405
+ async function executeSend(args) {
406
+ // Validate inputs (defense-in-depth, MCP SDK also validates)
407
+ validateSendArgs(args);
408
+ // Convert cents to dollars for CLI (CLI expects dollar amount)
409
+ const amountDollars = args.amount / 100;
410
+ // Calculate fee breakdown (5% Ra Pay application fee)
411
+ const rapayFee = amountDollars * 0.05;
412
+ const recipientReceives = amountDollars - rapayFee;
413
+ // If not confirmed, return fee preview (no payment executed)
414
+ // This ensures fee is disclosed BEFORE user authorizes payment
415
+ if (!args.user_confirmed) {
416
+ return JSON.stringify({
417
+ status: "confirmation_required",
418
+ message: "Please confirm this payment with the user before proceeding.",
419
+ payment_details: {
420
+ amount: amountDollars,
421
+ currency: "USD",
422
+ recipient: args.recipient_id,
423
+ purpose: args.business_purpose,
424
+ },
425
+ fee_breakdown: {
426
+ rapay_fee: rapayFee,
427
+ rapay_fee_percent: "5%",
428
+ recipient_receives: recipientReceives,
429
+ },
430
+ next_step: "Call ra_send again with user_confirmed=true after user approves the fee breakdown.",
431
+ }, null, 2);
432
+ }
433
+ // User confirmed - execute payment
434
+ const cliArgs = [
435
+ "send",
436
+ String(amountDollars),
437
+ "USD",
438
+ "to",
439
+ args.recipient_id,
440
+ "--for",
441
+ args.business_purpose,
442
+ "--json",
443
+ "--confirm", // Only passed when user_confirmed=true
444
+ ];
445
+ return executeCliCommand(cliArgs);
446
+ }
447
+ /**
448
+ * Execute ra subscribe command
449
+ */
450
+ async function executeSubscribe(args) {
451
+ // Validate inputs (defense-in-depth, MCP SDK also validates)
452
+ validateSubscribeArgs(args);
453
+ const cliArgs = [
454
+ "subscribe",
455
+ args.price_id,
456
+ args.customer_email,
457
+ "--json",
458
+ "--confirm", // Skip CLI confirmation (MCP client handles approval)
459
+ ];
460
+ return executeCliCommand(cliArgs);
461
+ }
462
+ /**
463
+ * Execute ra refund command (opens Stripe Dashboard)
464
+ */
465
+ async function executeRefund() {
466
+ const cliArgs = ["refund", "--json"];
467
+ return executeCliCommand(cliArgs);
468
+ }
469
+ /**
470
+ * Execute ra balance command
471
+ */
472
+ async function executeBalance() {
473
+ const cliArgs = ["balance", "--json"];
474
+ return executeCliCommand(cliArgs);
475
+ }
476
+ /**
477
+ * Execute ra history command
478
+ */
479
+ async function executeHistory(args) {
480
+ // Validate inputs (defense-in-depth, MCP SDK also validates)
481
+ validateHistoryArgs(args);
482
+ const cliArgs = ["history", "--json"];
483
+ if (args.limit) {
484
+ cliArgs.push("--limit", String(args.limit));
485
+ }
486
+ return executeCliCommand(cliArgs);
487
+ }
488
+ /**
489
+ * Execute ra whoami command
490
+ */
491
+ async function executeWhoami() {
492
+ const cliArgs = ["whoami", "--json"];
493
+ return executeCliCommand(cliArgs);
494
+ }
495
+ //# sourceMappingURL=handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Ra Pay MCP Server - Entry Point
4
+ *
5
+ * MCP (Model Context Protocol) server for AI agent payment automation.
6
+ * Wraps Ra Pay CLI as subprocess, never sees credentials directly.
7
+ *
8
+ * @see MCP-SERVER-PLAN.md for full specification
9
+ * @see https://modelcontextprotocol.io for MCP protocol documentation
10
+ *
11
+ * Perplexity Security Review: APPROVED (98% confidence)
12
+ * - All 5 security gaps addressed
13
+ * - Privacy preserved (dumb pipe model intact)
14
+ * - No blockers
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
package/dist/index.js ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Ra Pay MCP Server - Entry Point
4
+ *
5
+ * MCP (Model Context Protocol) server for AI agent payment automation.
6
+ * Wraps Ra Pay CLI as subprocess, never sees credentials directly.
7
+ *
8
+ * @see MCP-SERVER-PLAN.md for full specification
9
+ * @see https://modelcontextprotocol.io for MCP protocol documentation
10
+ *
11
+ * Perplexity Security Review: APPROVED (98% confidence)
12
+ * - All 5 security gaps addressed
13
+ * - Privacy preserved (dumb pipe model intact)
14
+ * - No blockers
15
+ */
16
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
17
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
18
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
19
+ import { TOOLS, logToolIntegrity } from "./tools.js";
20
+ import { handleToolCall } from "./handlers.js";
21
+ /**
22
+ * Server metadata
23
+ */
24
+ const SERVER_NAME = "rapay-mcp";
25
+ const SERVER_VERSION = "1.1.3";
26
+ /**
27
+ * Initialize MCP server
28
+ */
29
+ const server = new Server({
30
+ name: SERVER_NAME,
31
+ version: SERVER_VERSION,
32
+ }, {
33
+ capabilities: {
34
+ tools: {},
35
+ },
36
+ });
37
+ /**
38
+ * Handle tools/list request
39
+ * Returns all 6 MVP tools with their schemas
40
+ */
41
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
42
+ return {
43
+ tools: TOOLS,
44
+ };
45
+ });
46
+ /**
47
+ * Handle tools/call request
48
+ * Executes the requested tool via CLI subprocess
49
+ */
50
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
51
+ const { name, arguments: args } = request.params;
52
+ try {
53
+ // Execute tool and get sanitized result
54
+ const result = await handleToolCall(name, args || {});
55
+ return {
56
+ content: [
57
+ {
58
+ type: "text",
59
+ text: result,
60
+ },
61
+ ],
62
+ };
63
+ }
64
+ catch (error) {
65
+ // Return error as MCP error response
66
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
67
+ return {
68
+ content: [
69
+ {
70
+ type: "text",
71
+ text: JSON.stringify({
72
+ error: "tool_execution_failed",
73
+ code: "TOOL_EXECUTION_FAILED",
74
+ message: errorMessage,
75
+ retryable: false,
76
+ }, null, 2),
77
+ },
78
+ ],
79
+ isError: true,
80
+ };
81
+ }
82
+ });
83
+ /**
84
+ * Start the MCP server with stdio transport
85
+ */
86
+ async function main() {
87
+ const transport = new StdioServerTransport();
88
+ // Log to stderr (stdout is reserved for MCP protocol)
89
+ console.error(`[${SERVER_NAME}] Starting Ra Pay MCP Server v${SERVER_VERSION}`);
90
+ console.error(`[${SERVER_NAME}] Transport: stdio`);
91
+ console.error(`[${SERVER_NAME}] Tools: ${TOOLS.map((t) => t.name).join(", ")}`);
92
+ // Verify tool integrity on startup
93
+ logToolIntegrity();
94
+ await server.connect(transport);
95
+ console.error(`[${SERVER_NAME}] Server running`);
96
+ }
97
+ // Handle graceful shutdown
98
+ process.on("SIGINT", () => {
99
+ console.error(`[${SERVER_NAME}] Shutting down...`);
100
+ process.exit(0);
101
+ });
102
+ process.on("SIGTERM", () => {
103
+ console.error(`[${SERVER_NAME}] Shutting down...`);
104
+ process.exit(0);
105
+ });
106
+ // Start server
107
+ main().catch((error) => {
108
+ console.error(`[${SERVER_NAME}] Fatal error:`, error);
109
+ process.exit(1);
110
+ });
111
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}