@payware/mcp-server 1.0.0 → 1.1.1

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 (47) hide show
  1. package/README.md +42 -4
  2. package/package.json +1 -1
  3. package/src/isv/data/index.js +23 -0
  4. package/src/isv/deep-links/delete-product-link.js +1 -1
  5. package/src/isv/deep-links/delete-transaction-link.js +1 -1
  6. package/src/isv/deep-links/get-product-link.js +1 -1
  7. package/src/isv/deep-links/get-transaction-link.js +1 -1
  8. package/src/isv/index.js +11 -1
  9. package/src/isv/poi/cancel-price.js +149 -0
  10. package/src/isv/poi/get-poi.js +190 -0
  11. package/src/isv/poi/get-qrcode.js +151 -0
  12. package/src/isv/poi/get-status.js +176 -0
  13. package/src/isv/poi/index.js +32 -0
  14. package/src/isv/poi/list-pois.js +168 -0
  15. package/src/isv/poi/set-price.js +225 -0
  16. package/src/isv/transactions/get-status.js +1 -1
  17. package/src/isv/transactions/transaction-history.js +2 -1
  18. package/src/mcp-proxy.js +2 -2
  19. package/src/merchant/data/export-report.js +3 -4
  20. package/src/merchant/data/generate-report.js +3 -4
  21. package/src/merchant/data/get-export-list.js +140 -0
  22. package/src/merchant/data/get-report-requests.js +125 -0
  23. package/src/merchant/data/get-report-status.js +3 -4
  24. package/src/merchant/data/index.js +64 -25
  25. package/src/merchant/data/list-reports.js +107 -0
  26. package/src/merchant/deep-links/delete-product-link.js +1 -1
  27. package/src/merchant/deep-links/delete-transaction-link.js +1 -1
  28. package/src/merchant/deep-links/get-product-link.js +1 -1
  29. package/src/merchant/deep-links/get-transaction-link.js +1 -1
  30. package/src/merchant/transactions/create-transaction.js +4 -2
  31. package/src/merchant/transactions/get-status.js +1 -1
  32. package/src/merchant/transactions/process-transaction.js +10 -1
  33. package/src/merchant/transactions/simulate-callback.js +11 -2
  34. package/src/merchant/transactions/transaction-history.js +1 -1
  35. package/src/payment-institution/data/index.js +23 -0
  36. package/src/payment-institution/deep-links/delete-transaction-link.js +1 -1
  37. package/src/payment-institution/deep-links/get-transaction-link.js +1 -1
  38. package/src/payment-institution/transactions/create-pi-transaction.js +2 -0
  39. package/src/payment-institution/transactions/finalize-transaction.js +1 -0
  40. package/src/payment-institution/transactions/get-transaction-history.js +1 -1
  41. package/src/payment-institution/transactions/get-transaction-status.js +1 -1
  42. package/src/payment-institution/transactions/process-pi-transaction.js +12 -0
  43. package/src/payment-institution/transactions/simulate-pi-callback.js +12 -2
  44. package/src/payment-institution/transactions/soundbite-transaction.js +2 -0
  45. package/src/shared/data/data-api.js +97 -0
  46. package/src/utils/code-examples/merchant/transactions.js +2 -1
  47. package/src/utils/code-examples/payment-institution/transactions.js +1 -0
@@ -0,0 +1,176 @@
1
+ import axios from 'axios';
2
+ import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
+ import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
+
5
+ /**
6
+ * Get POI status via ISV authentication
7
+ * @param {Object} params - Parameters for status request
8
+ * @returns {Object} POI status response
9
+ */
10
+ export async function getPOIStatus({ poiId, merchantPartnerId, oauth2Token, useSandbox = true }) {
11
+ if (!poiId) {
12
+ throw new Error('POI ID is required');
13
+ }
14
+
15
+ if (!merchantPartnerId) {
16
+ throw new Error('Merchant Partner ID is required for ISV operations');
17
+ }
18
+
19
+ if (!oauth2Token) {
20
+ throw new Error('OAuth2 token is required for ISV operations');
21
+ }
22
+
23
+ const isvPartnerId = getPartnerIdSafe();
24
+ const privateKey = getPrivateKeySafe(useSandbox);
25
+
26
+ const jwtData = await createJWTForPartner({
27
+ partnerId: isvPartnerId,
28
+ privateKey,
29
+ requestBody: null,
30
+ merchantId: merchantPartnerId,
31
+ oauth2Token
32
+ });
33
+
34
+ const headers = {
35
+ 'Authorization': `Bearer ${jwtData.token}`,
36
+ 'Content-Type': 'application/json',
37
+ 'Api-Version': '1'
38
+ };
39
+
40
+ try {
41
+ const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
42
+ const response = await axios.get(`${baseUrl}/poi/${poiId}/status`, { headers });
43
+
44
+ return {
45
+ success: true,
46
+ status: response.data,
47
+ requestId: response.headers['x-request-id'],
48
+ timestamp: new Date().toISOString()
49
+ };
50
+ } catch (error) {
51
+ return {
52
+ success: false,
53
+ error: {
54
+ message: error.response?.data?.message || error.message,
55
+ status: error.response?.status,
56
+ code: error.response?.data?.code,
57
+ details: error.response?.data
58
+ },
59
+ timestamp: new Date().toISOString()
60
+ };
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Get POI status tool implementation for ISV
66
+ */
67
+ export const getPOIStatusTool = {
68
+ name: "payware_poi_get_status",
69
+ description: `Get current status of a POI including any pending payment.
70
+
71
+ **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
72
+ **Endpoint:** GET /poi/{poiId}/status
73
+ **Use Case:** Check if a POI is idle, has a pending price, or is busy with a payment.
74
+
75
+ **POI States:**
76
+ - IDLE: Ready for new payment
77
+ - READY: Price set, waiting for customer scan
78
+ - BUSY: Payment in progress
79
+ - DISABLED: Not accepting payments
80
+
81
+ **Required:** POI ID, Merchant Partner ID, and OAuth2 token.`,
82
+
83
+ inputSchema: {
84
+ type: "object",
85
+ required: ["poiId", "merchantPartnerId", "oauth2Token"],
86
+ properties: {
87
+ poiId: {
88
+ type: "string",
89
+ description: "The POI identifier (format: pi + 8 alphanumeric chars, e.g., piABC12345)"
90
+ },
91
+ merchantPartnerId: {
92
+ type: "string",
93
+ description: "Partner ID of the target merchant (8 alphanumeric characters)"
94
+ },
95
+ oauth2Token: {
96
+ type: "string",
97
+ description: "OAuth2 access token obtained from the merchant"
98
+ },
99
+ useSandbox: {
100
+ type: "boolean",
101
+ description: "Use sandbox environment for testing",
102
+ default: true
103
+ }
104
+ }
105
+ },
106
+
107
+ async handler(args) {
108
+ const { poiId, merchantPartnerId, oauth2Token, useSandbox = true } = args;
109
+
110
+ if (!poiId) {
111
+ throw new Error("POI ID is required");
112
+ }
113
+
114
+ if (!merchantPartnerId) {
115
+ throw new Error("Merchant Partner ID is required");
116
+ }
117
+
118
+ if (!oauth2Token) {
119
+ throw new Error("OAuth2 token is required");
120
+ }
121
+
122
+ const result = await getPOIStatus({ poiId, merchantPartnerId, oauth2Token, useSandbox });
123
+
124
+ if (result.success) {
125
+ const status = result.status;
126
+ const statusEmoji = {
127
+ 'IDLE': '🟢',
128
+ 'READY': '🟡',
129
+ 'BUSY': '🔴',
130
+ 'DISABLED': '⚫'
131
+ }[status.status] || '⚪';
132
+
133
+ let pendingInfo = '';
134
+ if (status.status === 'READY' || status.status === 'BUSY') {
135
+ pendingInfo = `
136
+ **Pending Payment:**
137
+ - Amount: ${status.pendingAmount} ${status.pendingCurrency}
138
+ - Expires: ${status.sessionExpiresAt || 'N/A'}${status.transactionId ? `\n- Transaction: ${status.transactionId}` : ''}`;
139
+ }
140
+
141
+ return {
142
+ content: [{
143
+ type: "text",
144
+ text: `${statusEmoji} **POI Status: ${status.status}**
145
+
146
+ **POI ID:** ${status.poiId}
147
+ **ISV -> Merchant:** ${getPartnerIdSafe()} -> ${merchantPartnerId}
148
+ ${pendingInfo}
149
+
150
+ **Status Meaning:**
151
+ ${status.status === 'IDLE' ? '✅ POI is ready to accept a new price' : ''}${status.status === 'READY' ? '⏳ Price set, waiting for customer to scan' : ''}${status.status === 'BUSY' ? '🔄 Customer scanned, payment in progress' : ''}${status.status === 'DISABLED' ? '🚫 POI is disabled and cannot accept payments' : ''}
152
+
153
+ **Request ID:** ${result.requestId || 'N/A'}
154
+ **Timestamp:** ${result.timestamp}`
155
+ }]
156
+ };
157
+ } else {
158
+ return {
159
+ content: [{
160
+ type: "text",
161
+ text: `❌ **Failed to Get POI Status**
162
+
163
+ **POI ID:** ${poiId}
164
+ **Error:** ${result.error.message}
165
+ **Status:** ${result.error.status || 'N/A'}
166
+
167
+ **Common Issues:**
168
+ - INVALID_POI_ID (400): POI ID format invalid (must be pi + 8 alphanumeric chars)
169
+ - POI_NOT_FOUND (404): POI doesn't exist
170
+
171
+ **Timestamp:** ${result.timestamp}`
172
+ }]
173
+ };
174
+ }
175
+ }
176
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * POI (Point of Interaction) tools for ISV partners
3
+ * Enables management of physical payment points with dynamic pricing
4
+ */
5
+
6
+ import { listPOIsTool } from './list-pois.js';
7
+ import { getPOITool } from './get-poi.js';
8
+ import { getPOIStatusTool } from './get-status.js';
9
+ import { setPOIPriceTool } from './set-price.js';
10
+ import { cancelPOIPriceTool } from './cancel-price.js';
11
+ import { getPOIQRCodeTool } from './get-qrcode.js';
12
+
13
+ /**
14
+ * All POI tools for ISV
15
+ */
16
+ export const isvPOITools = [
17
+ listPOIsTool,
18
+ getPOITool,
19
+ getPOIStatusTool,
20
+ setPOIPriceTool,
21
+ cancelPOIPriceTool,
22
+ getPOIQRCodeTool
23
+ ];
24
+
25
+ export {
26
+ listPOIsTool,
27
+ getPOITool,
28
+ getPOIStatusTool,
29
+ setPOIPriceTool,
30
+ cancelPOIPriceTool,
31
+ getPOIQRCodeTool
32
+ };
@@ -0,0 +1,168 @@
1
+ import axios from 'axios';
2
+ import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
+ import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
+
5
+ /**
6
+ * List all POIs for a merchant via ISV authentication
7
+ * @param {Object} params - Parameters for list request
8
+ * @returns {Object} List of POIs response
9
+ */
10
+ export async function listPOIs({ merchantPartnerId, oauth2Token, useSandbox = true }) {
11
+ if (!merchantPartnerId) {
12
+ throw new Error('Merchant Partner ID is required for ISV operations');
13
+ }
14
+
15
+ if (!oauth2Token) {
16
+ throw new Error('OAuth2 token is required for ISV operations');
17
+ }
18
+
19
+ // Get ISV credentials
20
+ const isvPartnerId = getPartnerIdSafe();
21
+ const privateKey = getPrivateKeySafe(useSandbox);
22
+
23
+ // Create ISV JWT token (GET request - no body)
24
+ const jwtData = await createJWTForPartner({
25
+ partnerId: isvPartnerId,
26
+ privateKey,
27
+ requestBody: null,
28
+ merchantId: merchantPartnerId,
29
+ oauth2Token
30
+ });
31
+
32
+ // Required headers as per payware API documentation
33
+ const headers = {
34
+ 'Authorization': `Bearer ${jwtData.token}`,
35
+ 'Content-Type': 'application/json',
36
+ 'Api-Version': '1'
37
+ };
38
+
39
+ try {
40
+ const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
41
+ const response = await axios.get(`${baseUrl}/poi`, { headers });
42
+
43
+ return {
44
+ success: true,
45
+ pois: response.data,
46
+ count: Array.isArray(response.data) ? response.data.length : 0,
47
+ requestId: response.headers['x-request-id'],
48
+ timestamp: new Date().toISOString()
49
+ };
50
+ } catch (error) {
51
+ return {
52
+ success: false,
53
+ error: {
54
+ message: error.response?.data?.message || error.message,
55
+ status: error.response?.status,
56
+ code: error.response?.data?.code,
57
+ details: error.response?.data
58
+ },
59
+ timestamp: new Date().toISOString()
60
+ };
61
+ }
62
+ }
63
+
64
+ /**
65
+ * List POIs tool implementation for ISV
66
+ */
67
+ export const listPOIsTool = {
68
+ name: "payware_poi_list",
69
+ description: `List all POIs (Points of Interaction) for a merchant.
70
+
71
+ **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
72
+ **Endpoint:** GET /poi
73
+ **Use Case:** Retrieve all physical payment points configured for a merchant.
74
+
75
+ POI states: IDLE (ready), READY (price set), BUSY (payment in progress), DISABLED.
76
+
77
+ **Required:** Merchant Partner ID and OAuth2 token for ISV authentication.`,
78
+
79
+ inputSchema: {
80
+ type: "object",
81
+ required: ["merchantPartnerId", "oauth2Token"],
82
+ properties: {
83
+ merchantPartnerId: {
84
+ type: "string",
85
+ description: "Partner ID of the target merchant (8 alphanumeric characters)"
86
+ },
87
+ oauth2Token: {
88
+ type: "string",
89
+ description: "OAuth2 access token obtained from the merchant"
90
+ },
91
+ useSandbox: {
92
+ type: "boolean",
93
+ description: "Use sandbox environment for testing",
94
+ default: true
95
+ }
96
+ }
97
+ },
98
+
99
+ async handler(args) {
100
+ const { merchantPartnerId, oauth2Token, useSandbox = true } = args;
101
+
102
+ if (!merchantPartnerId) {
103
+ throw new Error("Merchant Partner ID is required for ISV operations");
104
+ }
105
+
106
+ if (!oauth2Token) {
107
+ throw new Error("OAuth2 token is required for ISV operations");
108
+ }
109
+
110
+ const result = await listPOIs({ merchantPartnerId, oauth2Token, useSandbox });
111
+
112
+ if (result.success) {
113
+ const poisList = result.pois.map(poi => {
114
+ const statusEmoji = {
115
+ 'IDLE': '🟢',
116
+ 'READY': '🟡',
117
+ 'BUSY': '🔴',
118
+ 'DISABLED': '⚫'
119
+ }[poi.status] || '⚪';
120
+
121
+ return `${statusEmoji} **${poi.name}** (${poi.poiId})
122
+ Shop: ${poi.shopName || poi.shopCode}
123
+ Status: ${poi.status}${poi.pendingAmount && poi.pendingAmount !== '0.00' ? ` | Pending: ${poi.pendingAmount} ${poi.pendingCurrency}` : ''}`;
124
+ }).join('\n\n');
125
+
126
+ return {
127
+ content: [{
128
+ type: "text",
129
+ text: `📍 **POIs Retrieved (ISV -> Merchant: ${merchantPartnerId})**
130
+
131
+ **Total POIs:** ${result.count}
132
+
133
+ ${poisList || 'No POIs found for this merchant.'}
134
+
135
+ **Status Legend:**
136
+ 🟢 IDLE - Ready for new payment
137
+ 🟡 READY - Price set, waiting for customer
138
+ 🔴 BUSY - Payment in progress
139
+ ⚫ DISABLED - Not accepting payments
140
+
141
+ **Request ID:** ${result.requestId || 'N/A'}
142
+ **Timestamp:** ${result.timestamp}`
143
+ }]
144
+ };
145
+ } else {
146
+ return {
147
+ content: [{
148
+ type: "text",
149
+ text: `❌ **Failed to List POIs**
150
+
151
+ **ISV -> Merchant:** ${getPartnerIdSafe()} -> ${merchantPartnerId}
152
+
153
+ **Error Details:**
154
+ - Message: ${result.error.message}
155
+ - Status: ${result.error.status || 'N/A'}
156
+ - Code: ${result.error.code || 'N/A'}
157
+
158
+ **Troubleshooting:**
159
+ 1. Verify OAuth2 token is valid
160
+ 2. Ensure merchant has POI feature enabled
161
+ 3. Check ISV authorization for merchant
162
+
163
+ **Timestamp:** ${result.timestamp}`
164
+ }]
165
+ };
166
+ }
167
+ }
168
+ };
@@ -0,0 +1,225 @@
1
+ import axios from 'axios';
2
+ import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
+ import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
+
5
+ /**
6
+ * Set price on a POI via ISV authentication
7
+ * @param {Object} params - Parameters for set price request
8
+ * @returns {Object} Set price response
9
+ */
10
+ export async function setPOIPrice({ poiId, amount, currency, reasonL1, reasonL2, timeToLive, callbackUrl, passbackParams, merchantPartnerId, oauth2Token, useSandbox = true }) {
11
+ if (!poiId) {
12
+ throw new Error('POI ID is required');
13
+ }
14
+
15
+ if (!amount) {
16
+ throw new Error('Amount is required');
17
+ }
18
+
19
+ if (!currency) {
20
+ throw new Error('Currency is required');
21
+ }
22
+
23
+ if (!reasonL1) {
24
+ throw new Error('Reason (reasonL1) is required');
25
+ }
26
+
27
+ if (!merchantPartnerId) {
28
+ throw new Error('Merchant Partner ID is required for ISV operations');
29
+ }
30
+
31
+ if (!oauth2Token) {
32
+ throw new Error('OAuth2 token is required for ISV operations');
33
+ }
34
+
35
+ const isvPartnerId = getPartnerIdSafe();
36
+ const privateKey = getPrivateKeySafe(useSandbox);
37
+
38
+ // Build request body
39
+ const requestBody = {
40
+ amount: String(amount),
41
+ currency: currency.toUpperCase(),
42
+ reasonL1
43
+ };
44
+
45
+ if (reasonL2) requestBody.reasonL2 = reasonL2;
46
+ if (timeToLive) requestBody.timeToLive = timeToLive;
47
+ if (callbackUrl) requestBody.callbackUrl = callbackUrl;
48
+ if (passbackParams) requestBody.passbackParams = passbackParams;
49
+
50
+ const jwtData = await createJWTForPartner({
51
+ partnerId: isvPartnerId,
52
+ privateKey,
53
+ requestBody,
54
+ merchantId: merchantPartnerId,
55
+ oauth2Token
56
+ });
57
+
58
+ const headers = {
59
+ 'Authorization': `Bearer ${jwtData.token}`,
60
+ 'Content-Type': 'application/json',
61
+ 'Api-Version': '1'
62
+ };
63
+
64
+ try {
65
+ const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
66
+ const response = await axios.put(`${baseUrl}/poi/${poiId}/price`, requestBody, { headers });
67
+
68
+ return {
69
+ success: true,
70
+ result: response.data,
71
+ requestId: response.headers['x-request-id'],
72
+ timestamp: new Date().toISOString()
73
+ };
74
+ } catch (error) {
75
+ return {
76
+ success: false,
77
+ error: {
78
+ message: error.response?.data?.message || error.message,
79
+ status: error.response?.status,
80
+ code: error.response?.data?.code,
81
+ details: error.response?.data
82
+ },
83
+ timestamp: new Date().toISOString()
84
+ };
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Set POI price tool implementation for ISV
90
+ */
91
+ export const setPOIPriceTool = {
92
+ name: "payware_poi_set_price",
93
+ description: `Set a pending price on a POI for customer payment.
94
+
95
+ **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
96
+ **Endpoint:** PUT /poi/{poiId}/price
97
+ **Use Case:** Set the amount a customer should pay when they scan the POI.
98
+
99
+ The POI will transition to READY state and wait for a customer scan until the TTL expires.
100
+
101
+ **Required:** POI ID, amount, currency, reason, Merchant Partner ID, and OAuth2 token.`,
102
+
103
+ inputSchema: {
104
+ type: "object",
105
+ required: ["poiId", "amount", "currency", "reasonL1", "merchantPartnerId", "oauth2Token"],
106
+ properties: {
107
+ poiId: {
108
+ type: "string",
109
+ description: "The POI identifier (format: pi + 8 alphanumeric chars, e.g., piABC12345)"
110
+ },
111
+ amount: {
112
+ type: "string",
113
+ description: "Payment amount (e.g., '25.50')"
114
+ },
115
+ currency: {
116
+ type: "string",
117
+ description: "ISO 4217 currency code (e.g., 'EUR', 'USD', 'BGN')"
118
+ },
119
+ reasonL1: {
120
+ type: "string",
121
+ description: "Payment description (e.g., 'Table 5', 'Order #123')"
122
+ },
123
+ reasonL2: {
124
+ type: "string",
125
+ description: "Additional description (optional)"
126
+ },
127
+ timeToLive: {
128
+ type: "integer",
129
+ description: "Seconds until price expires (60-600, default: 120)"
130
+ },
131
+ callbackUrl: {
132
+ type: "string",
133
+ description: "Override callback URL for this payment (optional)"
134
+ },
135
+ passbackParams: {
136
+ type: "string",
137
+ description: "Data to pass back in callback (optional, max 200 chars)"
138
+ },
139
+ merchantPartnerId: {
140
+ type: "string",
141
+ description: "Partner ID of the target merchant (8 alphanumeric characters)"
142
+ },
143
+ oauth2Token: {
144
+ type: "string",
145
+ description: "OAuth2 access token obtained from the merchant"
146
+ },
147
+ useSandbox: {
148
+ type: "boolean",
149
+ description: "Use sandbox environment for testing",
150
+ default: true
151
+ }
152
+ }
153
+ },
154
+
155
+ async handler(args) {
156
+ const { poiId, amount, currency, reasonL1, reasonL2, timeToLive, callbackUrl, passbackParams, merchantPartnerId, oauth2Token, useSandbox = true } = args;
157
+
158
+ if (!poiId) throw new Error("POI ID is required");
159
+ if (!amount) throw new Error("Amount is required");
160
+ if (!currency) throw new Error("Currency is required");
161
+ if (!reasonL1) throw new Error("Reason (reasonL1) is required");
162
+ if (!merchantPartnerId) throw new Error("Merchant Partner ID is required");
163
+ if (!oauth2Token) throw new Error("OAuth2 token is required");
164
+
165
+ const result = await setPOIPrice({
166
+ poiId, amount, currency, reasonL1, reasonL2, timeToLive, callbackUrl, passbackParams,
167
+ merchantPartnerId, oauth2Token, useSandbox
168
+ });
169
+
170
+ if (result.success) {
171
+ const data = result.result;
172
+
173
+ return {
174
+ content: [{
175
+ type: "text",
176
+ text: `✅ **Price Set Successfully**
177
+
178
+ **POI ID:** ${data.poiId || poiId}
179
+ **Status:** 🟡 ${data.status || 'READY'}
180
+
181
+ **Payment Details:**
182
+ - Amount: **${data.amount || amount} ${data.currency || currency}**
183
+ - Reason: ${reasonL1}${reasonL2 ? ` - ${reasonL2}` : ''}
184
+
185
+ **Session:**
186
+ - Token: ${data.sessionToken || 'N/A'}
187
+ - Expires: ${data.sessionExpiresAt || 'N/A'}
188
+
189
+ **Next Steps:**
190
+ 1. Customer scans the POI (QR code, NFC tag, or barcode)
191
+ 2. Customer sees the amount and confirms payment
192
+ 3. You receive a callback when payment completes
193
+
194
+ **ISV -> Merchant:** ${getPartnerIdSafe()} -> ${merchantPartnerId}
195
+ **Request ID:** ${result.requestId || 'N/A'}
196
+ **Timestamp:** ${result.timestamp}`
197
+ }]
198
+ };
199
+ } else {
200
+ return {
201
+ content: [{
202
+ type: "text",
203
+ text: `❌ **Failed to Set Price**
204
+
205
+ **POI ID:** ${poiId}
206
+ **Attempted:** ${amount} ${currency}
207
+
208
+ **Error:** ${result.error.message}
209
+ **Code:** ${result.error.code || 'N/A'}
210
+ **Status:** ${result.error.status || 'N/A'}
211
+
212
+ **Common Issues:**
213
+ - INVALID_POI_ID (400): POI ID format invalid (must be pi + 8 alphanumeric chars)
214
+ - POI_NOT_FOUND (404): POI doesn't exist or doesn't belong to merchant
215
+ - POI_DISABLED (409): POI is disabled
216
+ - POI_NOT_IDLE (409): POI already has a pending price (cancel it first)
217
+ - INVALID_AMOUNT (400): Check amount format (e.g., '25.50')
218
+ - UNKNOWN_CURRENCY (400): Invalid currency code
219
+
220
+ **Timestamp:** ${result.timestamp}`
221
+ }]
222
+ };
223
+ }
224
+ }
225
+ };
@@ -159,7 +159,7 @@ export const getTransactionStatusTool = {
159
159
  - ID: ${result.transaction.id || 'N/A'}
160
160
  - Type: ${result.transaction.type || 'N/A'}
161
161
  - Amount: ${result.transaction.trData ? `${result.transaction.trData.amount} ${result.transaction.trData.currency}` : 'N/A'}
162
- - Description: ${result.transaction.description || 'N/A'}
162
+ ${result.transaction.paymentMethod ? `- Payment Method: ${result.transaction.paymentMethod}\n` : ''}- Description: ${result.transaction.description || 'N/A'}
163
163
  - Created: ${result.transaction.createdAt || 'N/A'}
164
164
  - Updated: ${result.transaction.updatedAt || 'N/A'}
165
165
 
@@ -140,7 +140,8 @@ Requires ISV authentication with merchant partner ID and OAuth2 token.`,
140
140
  'CANCELLED': '🚫'
141
141
  };
142
142
  const emoji = statusEmojis[tx.status] || '❓';
143
- return ` ${emoji} **${tx.id}** - ${tx.trData?.amount || '0.00'} ${tx.trData?.currency || 'EUR'} - ${tx.status} - ${tx.createdAt || 'N/A'}`;
143
+ const paymentInfo = tx.paymentMethod ? ` [${tx.paymentMethod}]` : '';
144
+ return ` ${emoji} **${tx.id}** - ${tx.trData?.amount || '0.00'} ${tx.trData?.currency || 'EUR'}${paymentInfo} - ${tx.status} - ${tx.createdAt || 'N/A'}`;
144
145
  };
145
146
 
146
147
  return {
package/src/mcp-proxy.js CHANGED
@@ -111,13 +111,13 @@ class PaywareMCPBridge {
111
111
  };
112
112
 
113
113
  process.on('SIGINT', async () => {
114
- console.log('\nShutting down MCP Bridge...');
114
+ console.error('\nShutting down MCP Bridge...');
115
115
  await this.server.close();
116
116
  process.exit(0);
117
117
  });
118
118
 
119
119
  process.on('SIGTERM', async () => {
120
- console.log('\nShutting down MCP Bridge...');
120
+ console.error('\nShutting down MCP Bridge...');
121
121
  await this.server.close();
122
122
  process.exit(0);
123
123
  });
@@ -27,8 +27,7 @@ export const exportReportTool = {
27
27
  },
28
28
  privateKey: {
29
29
  type: "string",
30
- description: "RSA private key for authentication. Uses environment-specific private key as default.",
31
- default: getPrivateKeySafe()
30
+ description: "RSA private key for authentication. Uses production private key as default (Data API is production-only)."
32
31
  }
33
32
  },
34
33
  required: ["requestId"]
@@ -39,11 +38,11 @@ export const exportReportTool = {
39
38
  requestId,
40
39
  outputFormat = EXPORT_FORMATS.PDF,
41
40
  partnerId = getPartnerIdSafe(),
42
- privateKey = getPrivateKeySafe()
41
+ privateKey = getPrivateKeySafe(false) // false = production (Data API is production-only)
43
42
  } = args;
44
43
 
45
44
  if (!partnerId || !privateKey) {
46
- throw new Error("Partner ID and private key are required. Set PAYWARE_PARTNER_ID and environment-specific private key variables or provide them as parameters.");
45
+ throw new Error("Partner ID and private key are required. Set PAYWARE_PARTNER_ID and PAYWARE_PRODUCTION_PRIVATE_KEY_PATH environment variables or provide them as parameters.");
47
46
  }
48
47
 
49
48
  try {
@@ -49,8 +49,7 @@ export const generateReportTool = {
49
49
  },
50
50
  privateKey: {
51
51
  type: "string",
52
- description: "RSA private key for authentication. Uses environment-specific private key as default.",
53
- default: getPrivateKeySafe()
52
+ description: "RSA private key for authentication. Uses production private key as default (Data API is production-only)."
54
53
  }
55
54
  },
56
55
  required: ["reportUnitId"]
@@ -65,11 +64,11 @@ export const generateReportTool = {
65
64
  locale = LOCALES.ENGLISH_US,
66
65
  timeZone = 'GMT',
67
66
  partnerId = getPartnerIdSafe(),
68
- privateKey = getPrivateKeySafe()
67
+ privateKey = getPrivateKeySafe(false) // false = production (Data API is production-only)
69
68
  } = args;
70
69
 
71
70
  if (!partnerId || !privateKey) {
72
- throw new Error("Partner ID and private key are required. Set PAYWARE_PARTNER_ID and environment-specific private key variables or provide them as parameters.");
71
+ throw new Error("Partner ID and private key are required. Set PAYWARE_PARTNER_ID and PAYWARE_PRODUCTION_PRIVATE_KEY_PATH environment variables or provide them as parameters.");
73
72
  }
74
73
 
75
74
  // Check for required date range on premium reports