@payware/mcp-server 1.3.3 → 1.5.0

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 (89) hide show
  1. package/.env.example +4 -0
  2. package/README.md +18 -0
  3. package/package.json +7 -9
  4. package/src/auth/rsa-keys.js +12 -6
  5. package/src/auth/sandbox-setup.js +2 -0
  6. package/src/config/toolsets.js +104 -0
  7. package/src/core/auth/jwt-factory.js +4 -1
  8. package/src/core/auth/jwt-token.js +4 -0
  9. package/src/index.js +10 -6
  10. package/src/isv/data/index.js +15 -14
  11. package/src/isv/deep-links/delete-product-link.js +3 -2
  12. package/src/isv/deep-links/delete-transaction-link.js +3 -2
  13. package/src/isv/deep-links/get-product-link.js +8 -6
  14. package/src/isv/deep-links/get-transaction-link.js +8 -6
  15. package/src/isv/index.js +6 -0
  16. package/src/isv/invitations/index.js +5 -0
  17. package/src/isv/oauth2/get-token-info.js +3 -0
  18. package/src/isv/oauth2/obtain-token.js +3 -0
  19. package/src/isv/oauth2/token-helper.js +2 -0
  20. package/src/isv/poi/cancel-price.js +2 -0
  21. package/src/isv/poi/get-poi.js +2 -0
  22. package/src/isv/poi/get-qrcode.js +40 -9
  23. package/src/isv/poi/get-status.js +2 -0
  24. package/src/isv/poi/list-pois.js +2 -0
  25. package/src/isv/poi/set-price.js +2 -0
  26. package/src/isv/products/audios.js +8 -2
  27. package/src/isv/products/create-product.js +2 -0
  28. package/src/isv/products/delete-product.js +2 -0
  29. package/src/isv/products/get-product-image.js +2 -0
  30. package/src/isv/products/get-product.js +2 -0
  31. package/src/isv/products/list-products.js +2 -0
  32. package/src/isv/products/schedules.js +6 -0
  33. package/src/isv/products/update-product.js +2 -0
  34. package/src/isv/reference/index.js +2 -0
  35. package/src/isv/transactions/cancel-transaction.js +2 -0
  36. package/src/isv/transactions/create-transaction.js +14 -2
  37. package/src/isv/transactions/get-status.js +3 -1
  38. package/src/isv/transactions/process-transaction.js +14 -2
  39. package/src/isv/transactions/simulate-callback.js +2 -0
  40. package/src/isv/transactions/transaction-history.js +2 -0
  41. package/src/merchant/data/export-report.js +2 -0
  42. package/src/merchant/data/generate-report.js +2 -0
  43. package/src/merchant/data/get-export-list.js +2 -0
  44. package/src/merchant/data/get-report-requests.js +2 -0
  45. package/src/merchant/data/get-report-status.js +2 -0
  46. package/src/merchant/data/index.js +15 -10
  47. package/src/merchant/data/list-reports.js +2 -0
  48. package/src/merchant/deep-links/delete-product-link.js +3 -2
  49. package/src/merchant/deep-links/delete-transaction-link.js +3 -2
  50. package/src/merchant/deep-links/get-product-link.js +8 -6
  51. package/src/merchant/deep-links/get-transaction-link.js +8 -6
  52. package/src/merchant/index.js +7 -1
  53. package/src/merchant/logs/index.js +4 -0
  54. package/src/merchant/products/audios.js +15 -14
  55. package/src/merchant/products/create-product.js +3 -2
  56. package/src/merchant/products/delete-product.js +3 -2
  57. package/src/merchant/products/get-product-image.js +3 -2
  58. package/src/merchant/products/get-product.js +3 -2
  59. package/src/merchant/products/list-products.js +3 -2
  60. package/src/merchant/products/schedules.js +11 -10
  61. package/src/merchant/products/update-product.js +3 -2
  62. package/src/merchant/transactions/cancel-transaction.js +4 -3
  63. package/src/merchant/transactions/create-transaction.js +14 -2
  64. package/src/merchant/transactions/get-status.js +4 -3
  65. package/src/merchant/transactions/process-transaction.js +17 -6
  66. package/src/merchant/transactions/simulate-callback.js +3 -0
  67. package/src/merchant/transactions/transaction-history.js +5 -4
  68. package/src/payment-institution/data/index.js +15 -14
  69. package/src/payment-institution/deep-links/delete-transaction-link.js +3 -2
  70. package/src/payment-institution/deep-links/get-transaction-link.js +8 -6
  71. package/src/payment-institution/transactions/create-pi-transaction.js +15 -4
  72. package/src/payment-institution/transactions/finalize-transaction.js +7 -4
  73. package/src/payment-institution/transactions/get-transaction-history.js +7 -4
  74. package/src/payment-institution/transactions/get-transaction-status.js +15 -12
  75. package/src/payment-institution/transactions/process-pi-transaction.js +19 -8
  76. package/src/payment-institution/transactions/simulate-pi-callback.js +3 -0
  77. package/src/payment-institution/transactions/soundbite-transaction.js +5 -4
  78. package/src/proxy-server.js +25 -0
  79. package/src/shared/placements/api.js +51 -0
  80. package/src/shared/placements/tools.js +519 -0
  81. package/src/shared/poi/poi-create-api.js +3 -0
  82. package/src/shared/products/products-api.js +36 -25
  83. package/src/shared/shops/shops-api.js +2 -0
  84. package/src/shared/tool-annotations.js +53 -0
  85. package/src/tools/advanced-code-generator.js +3 -0
  86. package/src/utils/format-request.js +2 -0
  87. package/src/utils/json-formatter.js +2 -0
  88. package/src/utils/server-info.js +2 -0
  89. package/src/utils/code-examples.js +0 -646
@@ -3,6 +3,7 @@ import { createJWTToken } from '../../core/auth/jwt-token.js';
3
3
  import { createMinimizedJSON } from '../../core/utils/json-serializer.js';
4
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
5
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
6
+ import { CHANGES, CREATES, READS } from '../../shared/tool-annotations.js';
6
7
 
7
8
  /**
8
9
  * Merchant invitations - how an ISV onboards a merchant onto payware.
@@ -181,6 +182,7 @@ ${result.error.guidance ? `\n${result.error.guidance}` : ''}
181
182
 
182
183
  export const createInvitationTool = {
183
184
  name: 'payware_isv_create_invitation',
185
+ annotations: CREATES,
184
186
  description: `Invite a merchant to join payware through this ISV. **This is the start of the ISV onboarding flow.**
185
187
 
186
188
  **Endpoint:** POST /isv/invitations -> 201 Created
@@ -300,6 +302,7 @@ to start acting on their behalf.
300
302
 
301
303
  export const listInvitationsTool = {
302
304
  name: 'payware_isv_list_invitations',
305
+ annotations: READS,
303
306
  description: `List the merchant invitations this ISV has created, newest first.
304
307
 
305
308
  **Endpoint:** GET /isv/invitations - paginated
@@ -362,6 +365,7 @@ to was deleted.
362
365
 
363
366
  export const getInvitationTool = {
364
367
  name: 'payware_isv_get_invitation',
368
+ annotations: READS,
365
369
  description: `Get full details of one invitation, including its link and the merchant data it pre-fills.
366
370
 
367
371
  **Endpoint:** GET /isv/invitations/{invitationId}
@@ -416,6 +420,7 @@ ${inv.invitationLink}
416
420
 
417
421
  export const cancelInvitationTool = {
418
422
  name: 'payware_isv_cancel_invitation',
423
+ annotations: CHANGES,
419
424
  description: `Cancel a PENDING invitation. **The link stops working immediately.**
420
425
 
421
426
  **Endpoint:** DELETE /isv/invitations/{invitationId} -> 204 No Content
@@ -5,8 +5,11 @@
5
5
  * Use this to check token status and present information in POS software UI.
6
6
  */
7
7
 
8
+ import { READS } from '../../shared/tool-annotations.js';
9
+
8
10
  export const getTokenInfoTool = {
9
11
  name: 'payware_authorization_oauth2_get_token_info',
12
+ annotations: READS,
10
13
  description: `Get information about an OAuth2 access token.
11
14
 
12
15
  This endpoint exposes information about access tokens, including their status.
@@ -5,8 +5,11 @@
5
5
  * This is the first step in the ISV authorization flow.
6
6
  */
7
7
 
8
+ import { CREATES } from '../../shared/tool-annotations.js';
9
+
8
10
  export const obtainTokenTool = {
9
11
  name: 'payware_authorization_oauth2_obtain_token',
12
+ annotations: CREATES,
10
13
  description: `Obtain an OAuth2 access token for a merchant.
11
14
 
12
15
  ISVs must be authorized by payware registered merchants to make requests on their behalf.
@@ -5,12 +5,14 @@
5
5
 
6
6
  import { obtainTokenTool } from './obtain-token.js';
7
7
  import { getTokenInfoTool } from './get-token-info.js';
8
+ import { CREATES } from '../../shared/tool-annotations.js';
8
9
 
9
10
  /**
10
11
  * Helper tool to create or find OAuth2 tokens with clear output
11
12
  */
12
13
  export const tokenHelperTool = {
13
14
  name: 'payware_authorization_oauth2_token_helper',
15
+ annotations: CREATES,
14
16
  description: `OAuth2 Token Helper - Create or manage tokens with clear output.
15
17
 
16
18
  This tool helps you:
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
+ import { CHANGES } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Cancel pending price on a POI via ISV authentication
@@ -57,6 +58,7 @@ export async function cancelPOIPrice({ poiId, merchantPartnerId, oauth2Token, us
57
58
  */
58
59
  export const cancelPOIPriceTool = {
59
60
  name: "payware_poi_cancel_price",
61
+ annotations: CHANGES,
60
62
  description: `Cancel a pending price on a POI, resetting it to IDLE state.
61
63
 
62
64
  **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
+ import { READS } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Get POI details via ISV authentication
@@ -61,6 +62,7 @@ export async function getPOI({ poiId, merchantPartnerId, oauth2Token, useSandbox
61
62
  */
62
63
  export const getPOITool = {
63
64
  name: "payware_poi_get",
65
+ annotations: READS,
64
66
  description: `Get details of a specific POI (Point of Interaction).
65
67
 
66
68
  **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
@@ -1,19 +1,41 @@
1
1
  import axios from 'axios';
2
- import { getSandboxUrl, getProductionUrl } from '../../config/env.js';
2
+ import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
+ import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
3
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
+ import { READS } from '../../shared/tool-annotations.js';
4
6
 
5
7
  /**
6
- * Get POI QR code image
7
- * Note: This endpoint is public and doesn't require authentication
8
+ * Get POI QR code image via ISV authentication
9
+ *
10
+ * Not a public endpoint: the server resolves the merchant from the token and only answers for that
11
+ * merchant's own POIs (ApiPOIController.getQRCode, V-05), so an unauthenticated request was refused.
8
12
  * @param {Object} params - Parameters for QR code request
9
13
  * @returns {Object} QR code response
10
14
  */
11
- export async function getPOIQRCode({ poiId, format = 'PNG', useSandbox = true }) {
15
+ export async function getPOIQRCode({ poiId, format = 'PNG', merchantPartnerId, oauth2Token, useSandbox = true }) {
12
16
  if (!poiId) {
13
17
  throw new Error('POI ID is required');
14
18
  }
15
19
 
20
+ if (!merchantPartnerId) {
21
+ throw new Error('Merchant Partner ID is required for ISV operations');
22
+ }
23
+
24
+ if (!oauth2Token) {
25
+ throw new Error('OAuth2 token is required for ISV operations');
26
+ }
27
+
28
+ // Create ISV JWT token (GET request - no body)
29
+ const jwtData = await createJWTForPartner({
30
+ partnerId: getPartnerIdSafe(),
31
+ privateKey: getPrivateKeySafe(useSandbox),
32
+ requestBody: null,
33
+ merchantId: merchantPartnerId,
34
+ oauth2Token
35
+ });
36
+
16
37
  const headers = {
38
+ 'Authorization': `Bearer ${jwtData.token}`,
17
39
  'Api-Version': '1'
18
40
  };
19
41
 
@@ -49,26 +71,35 @@ export async function getPOIQRCode({ poiId, format = 'PNG', useSandbox = true })
49
71
  */
50
72
  export const getPOIQRCodeTool = {
51
73
  name: "payware_poi_get_qrcode",
74
+ annotations: READS,
52
75
  description: `Generate a QR code image for a POI that customers can scan.
53
76
 
54
77
  **Endpoint:** GET /poi/{poiId}/image
55
- **Authentication:** Public endpoint (no auth required)
78
+ **Authentication:** On behalf of the merchant that owns the POI
56
79
  **Use Case:** Generate QR codes for printing or displaying on screens.
57
80
 
58
81
  **Formats:** PNG (default), SVG, JPG
59
82
 
60
83
  Returns base64-encoded image data that can be saved or displayed.
61
84
 
62
- **Required:** POI ID only.`,
85
+ **Required:** POI ID, and the merchant partner ID and OAuth2 token to act on its behalf.`,
63
86
 
64
87
  inputSchema: {
65
88
  type: "object",
66
- required: ["poiId"],
89
+ required: ["poiId", "merchantPartnerId", "oauth2Token"],
67
90
  properties: {
68
91
  poiId: {
69
92
  type: "string",
70
93
  description: "The POI identifier (format: pi + 8 alphanumeric chars, e.g., piABC12345)"
71
94
  },
95
+ merchantPartnerId: {
96
+ type: "string",
97
+ description: "Partner ID of the target merchant (8 alphanumeric characters)"
98
+ },
99
+ oauth2Token: {
100
+ type: "string",
101
+ description: "OAuth2 access token obtained from the merchant"
102
+ },
72
103
  format: {
73
104
  type: "string",
74
105
  enum: ["PNG", "SVG", "JPG"],
@@ -84,11 +115,11 @@ Returns base64-encoded image data that can be saved or displayed.
84
115
  },
85
116
 
86
117
  async handler(args) {
87
- const { poiId, format = 'PNG', useSandbox = true } = args;
118
+ const { poiId, format = 'PNG', merchantPartnerId, oauth2Token, useSandbox = true } = args;
88
119
 
89
120
  if (!poiId) throw new Error("POI ID is required");
90
121
 
91
- const result = await getPOIQRCode({ poiId, format, useSandbox });
122
+ const result = await getPOIQRCode({ poiId, format, merchantPartnerId, oauth2Token, useSandbox });
92
123
 
93
124
  if (result.success) {
94
125
  const img = result.image;
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
+ import { READS } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Get POI status via ISV authentication
@@ -61,6 +62,7 @@ export async function getPOIStatus({ poiId, sessionToken, merchantPartnerId, oau
61
62
  */
62
63
  export const getPOIStatusTool = {
63
64
  name: "payware_poi_get_status",
65
+ annotations: READS,
64
66
  description: `Get the current status of a POI and the outcome of its sales.
65
67
 
66
68
  **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
+ import { READS } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * List all POIs for a merchant via ISV authentication
@@ -58,6 +59,7 @@ export async function listPOIs({ merchantPartnerId, oauth2Token, useSandbox = tr
58
59
  */
59
60
  export const listPOIsTool = {
60
61
  name: "payware_poi_list",
62
+ annotations: READS,
61
63
  description: `List all POIs (Points of Interaction) for a merchant.
62
64
 
63
65
  **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
+ import { CHANGES } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Set price on a POI via ISV authentication
@@ -77,6 +78,7 @@ export async function setPOIPrice({ poiId, amount, currency, ttlSeconds, merchan
77
78
  */
78
79
  export const setPOIPriceTool = {
79
80
  name: "payware_poi_set_price",
81
+ annotations: CHANGES,
80
82
  description: `Set a pending price on a POI for customer payment.
81
83
 
82
84
  **ISV Authentication:** Uses ISV JWT with merchant partner ID and OAuth2 token.
@@ -6,6 +6,7 @@ import {
6
6
  deleteAudio
7
7
  } from '../../shared/products/products-api.js';
8
8
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
9
+ import { CHANGES, CREATES, READS } from '../../shared/tool-annotations.js';
9
10
 
10
11
  // Common ISV authentication properties
11
12
  const ISV_AUTH_PROPS = {
@@ -46,9 +47,10 @@ function validateISVAuth(args) {
46
47
  */
47
48
  export const registerAudioTool = {
48
49
  name: "payware_products_register_audio",
50
+ annotations: CREATES,
49
51
  description: `Register an audio file (soundbite) for a merchant's product (ISV operation).
50
52
 
51
- **Supported formats:** Most audio/video formats (up to 200MB)
53
+ **Supported formats:** MP3, WAV, OGG, M4A, FLAC, AAC, WMA, MP4, MOV, up to 100 MB, holding 2 to 120 seconds of audio
52
54
  **Note:** For video files, only the audio channel is registered`,
53
55
 
54
56
  inputSchema: {
@@ -139,6 +141,7 @@ ${audio.status === '1' ? '✅ Audio is ready for use in soundbite transactions'
139
141
  */
140
142
  export const getAudiosTool = {
141
143
  name: "payware_products_get_audios",
144
+ annotations: READS,
142
145
  description: "Get all registered audio files for a merchant's product (ISV operation)",
143
146
 
144
147
  inputSchema: {
@@ -225,6 +228,7 @@ ${audiosList}`
225
228
  */
226
229
  export const getAudioTool = {
227
230
  name: "payware_products_get_audio",
231
+ annotations: READS,
228
232
  description: "Get detailed information about a specific audio file (ISV operation)",
229
233
 
230
234
  inputSchema: {
@@ -305,6 +309,7 @@ ${audio.status === '1' ? '✅ **Ready:** Audio is processed and ready for soundb
305
309
  */
306
310
  export const updateAudioTool = {
307
311
  name: "payware_products_update_audio",
312
+ annotations: CHANGES,
308
313
  description: "Update audio information (title) or reassign audio to another product (ISV operation)",
309
314
 
310
315
  inputSchema: {
@@ -327,7 +332,7 @@ export const updateAudioTool = {
327
332
  },
328
333
  newProductId: {
329
334
  type: "string",
330
- description: "New product ID to reassign audio to (starts with 'pr')",
335
+ description: "Product to move the audio to (starts with 'pr'). Sent as a transfer, which keeps the fingerprint; the target must be in the same shop",
331
336
  pattern: "^pr[a-zA-Z0-9]+$"
332
337
  },
333
338
  useSandbox: {
@@ -400,6 +405,7 @@ ${newProductId ? `- Reassigned from product ${productId} to ${newProductId}` : '
400
405
  */
401
406
  export const deleteAudioTool = {
402
407
  name: "payware_products_delete_audio",
408
+ annotations: CHANGES,
403
409
  description: "Delete an audio file from a merchant's product (ISV operation). This action cannot be undone.",
404
410
 
405
411
  inputSchema: {
@@ -1,12 +1,14 @@
1
1
  import { createProduct } from '../../shared/products/products-api.js';
2
2
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
3
3
  import { PRODUCT_TYPES, OVERLAP_PRIORITY } from '../../shared/products/products-api.js';
4
+ import { CREATES } from '../../shared/tool-annotations.js';
4
5
 
5
6
  /**
6
7
  * Create product tool implementation for ISVs
7
8
  */
8
9
  export const createProductTool = {
9
10
  name: "payware_products_create_product",
11
+ annotations: CREATES,
10
12
  description: `Create a new product for inventory management and payment processing on behalf of a merchant (ISV operation).
11
13
 
12
14
  **ISV Authentication**: Requires ISV credentials and OAuth2 token from target merchant.
@@ -1,11 +1,13 @@
1
1
  import { deleteProduct } from '../../shared/products/products-api.js';
2
2
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
3
+ import { CHANGES } from '../../shared/tool-annotations.js';
3
4
 
4
5
  /**
5
6
  * Delete product tool implementation for ISVs
6
7
  */
7
8
  export const deleteProductTool = {
8
9
  name: "payware_products_delete_product",
10
+ annotations: CHANGES,
9
11
  description: "Delete a product from a merchant account (ISV operation). This action cannot be undone.",
10
12
 
11
13
  inputSchema: {
@@ -1,12 +1,14 @@
1
1
  import { getProductImage } from '../../shared/products/products-api.js';
2
2
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
3
3
  import { IMAGE_TYPES, IMAGE_FORMATS, QR_ERROR_CORRECTION, BARCODE_LOCATIONS } from '../../shared/products/products-api.js';
4
+ import { READS } from '../../shared/tool-annotations.js';
4
5
 
5
6
  /**
6
7
  * Get product image tool implementation for ISVs
7
8
  */
8
9
  export const getProductImageTool = {
9
10
  name: "payware_products_get_product_image",
11
+ annotations: READS,
10
12
  description: `Generate a QR code or barcode image for a merchant's product (ISV operation).`,
11
13
 
12
14
  inputSchema: {
@@ -1,11 +1,13 @@
1
1
  import { getProduct } from '../../shared/products/products-api.js';
2
2
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
3
+ import { READS } from '../../shared/tool-annotations.js';
3
4
 
4
5
  /**
5
6
  * Get product tool implementation for ISVs
6
7
  */
7
8
  export const getProductTool = {
8
9
  name: "payware_products_get_product",
10
+ annotations: READS,
9
11
  description: "Get detailed information about a specific product by ID (ISV operation)",
10
12
 
11
13
  inputSchema: {
@@ -1,11 +1,13 @@
1
1
  import { getProducts } from '../../shared/products/products-api.js';
2
2
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
3
+ import { READS } from '../../shared/tool-annotations.js';
3
4
 
4
5
  /**
5
6
  * List products tool implementation for ISVs
6
7
  */
7
8
  export const listProductsTool = {
8
9
  name: "payware_products_list_products",
10
+ annotations: READS,
9
11
  description: "Get a list of all products for a merchant account (ISV operation)",
10
12
 
11
13
  inputSchema: {
@@ -7,6 +7,7 @@ import {
7
7
  } from '../../shared/products/products-api.js';
8
8
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
9
9
  import { PRICE_CORRECTION_TYPES, CORRECTION_TYPES } from '../../shared/products/products-api.js';
10
+ import { CHANGES, CREATES, READS } from '../../shared/tool-annotations.js';
10
11
 
11
12
  // Common ISV authentication properties
12
13
  const ISV_AUTH_PROPS = {
@@ -47,6 +48,7 @@ function validateISVAuth(args) {
47
48
  */
48
49
  export const createScheduleTool = {
49
50
  name: "payware_products_create_schedule",
51
+ annotations: CREATES,
50
52
  description: "Create a price schedule for a merchant's product (ISV operation)",
51
53
 
52
54
  inputSchema: {
@@ -172,6 +174,7 @@ export const createScheduleTool = {
172
174
  */
173
175
  export const getSchedulesTool = {
174
176
  name: "payware_products_get_schedules",
177
+ annotations: READS,
175
178
  description: "Get all price schedules for a merchant's product (ISV operation)",
176
179
 
177
180
  inputSchema: {
@@ -258,6 +261,7 @@ ${schedulesList}`
258
261
  */
259
262
  export const getScheduleTool = {
260
263
  name: "payware_products_get_schedule",
264
+ annotations: READS,
261
265
  description: "Get detailed information about a specific price schedule (ISV operation)",
262
266
 
263
267
  inputSchema: {
@@ -341,6 +345,7 @@ export const getScheduleTool = {
341
345
  */
342
346
  export const updateScheduleTool = {
343
347
  name: "payware_products_update_schedule",
348
+ annotations: CHANGES,
344
349
  description: "Update an existing price schedule (ISV operation)",
345
350
 
346
351
  inputSchema: {
@@ -452,6 +457,7 @@ export const updateScheduleTool = {
452
457
  */
453
458
  export const deleteScheduleTool = {
454
459
  name: "payware_products_delete_schedule",
460
+ annotations: CHANGES,
455
461
  description: "Delete a price schedule (ISV operation). This action cannot be undone.",
456
462
 
457
463
  inputSchema: {
@@ -1,12 +1,14 @@
1
1
  import { updateProduct } from '../../shared/products/products-api.js';
2
2
  import { getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
3
3
  import { PRODUCT_TYPES, OVERLAP_PRIORITY } from '../../shared/products/products-api.js';
4
+ import { CHANGES } from '../../shared/tool-annotations.js';
4
5
 
5
6
  /**
6
7
  * Update product tool implementation for ISVs
7
8
  */
8
9
  export const updateProductTool = {
9
10
  name: "payware_products_update_product",
11
+ annotations: CHANGES,
10
12
  description: `Update an existing product on behalf of a merchant (ISV operation). Only provide the fields you want to change.`,
11
13
 
12
14
  inputSchema: {
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTToken } from '../../core/auth/jwt-token.js';
3
3
  import { apiErrorResult } from '../../shared/api-errors.js';
4
4
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
5
+ import { READS } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Reference data - the enumerations a merchant registration form has to be filled in with.
@@ -129,6 +130,7 @@ const DATASET_DOCS = Object.entries(DATASETS)
129
130
 
130
131
  export const referenceDataTool = {
131
132
  name: 'payware_reference_lookup',
133
+ annotations: READS,
132
134
  description: `Look up payware reference data - the enumerations a merchant registration form needs.
133
135
 
134
136
  **Endpoints:** GET /isv/reference/{legal-forms, business-activities, currencies, languages, jurisdictions}
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { describeApiError } from '../../shared/api-errors.js';
5
+ import { CHANGES } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Cancel a transaction via payware API as an ISV
@@ -77,6 +78,7 @@ export async function cancelTransaction({ transactionId, statusMessage, merchant
77
78
 
78
79
  export const cancelTransactionTool = {
79
80
  name: 'payware_operations_cancel_transaction',
81
+ annotations: CHANGES,
80
82
  description: `Cancel an active transaction as an ISV on behalf of a merchant.
81
83
 
82
84
  **Endpoint:** PATCH /transactions/{transactionId} with \`{"status":"CANCELLED","statusMessage":"..."}\`
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { describeApiError } from '../../shared/api-errors.js';
5
+ import { CREATES } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Create a transaction via payware API on behalf of a merchant (ISV)
@@ -36,6 +37,7 @@ export async function createTransaction({
36
37
  barBarHeight,
37
38
  barFontSize,
38
39
  barHumanReadableLocation,
40
+ idempotencyKey,
39
41
  useSandbox = true
40
42
  }) {
41
43
  // ISV-specific validation
@@ -131,13 +133,17 @@ export async function createTransaction({
131
133
  headers: {
132
134
  'Authorization': `Bearer ${jwtData.token}`,
133
135
  'Content-Type': 'application/json',
134
- 'Api-Version': '1'
136
+ 'Api-Version': '1',
137
+ ...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
135
138
  },
136
139
  // Tell axios to send the string as-is, don't serialize it again
137
140
  transformRequest: [(data) => data]
138
141
  });
139
142
 
140
- return response.data;
143
+ // A retry answered from the first call (Idempotency-Key) says so in a header, not in the body.
144
+ return response.headers?.['idempotent-replayed'] === 'true'
145
+ ? { ...response.data, replayed: true }
146
+ : response.data;
141
147
  } catch (error) {
142
148
  throw describeApiError(error, 'call the payware API');
143
149
  }
@@ -145,6 +151,7 @@ export async function createTransaction({
145
151
 
146
152
  export const createTransactionTool = {
147
153
  name: 'payware_operations_create_transaction',
154
+ annotations: CREATES,
148
155
  description: `Create a new transaction through payware as an ISV on behalf of a merchant.
149
156
 
150
157
  ISV partners can create transactions for merchants they have authorization for via OAuth2.
@@ -198,6 +205,11 @@ merchant role if the terminal producer is meant to be attributed.
198
205
  type: 'object',
199
206
  required: ['merchantPartnerId', 'oauth2Token', 'reasonL1'],
200
207
  properties: {
208
+ idempotencyKey: {
209
+ type: "string",
210
+ description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
211
+ pattern: "^[\\x21-\\x7E]{1,255}$"
212
+ },
201
213
  // ISV Authentication
202
214
  merchantPartnerId: {
203
215
  type: 'string',
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
4
  import { apiErrorResult } from '../../shared/api-errors.js';
5
+ import { READS } from '../../shared/tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Get transaction status from payware API as an ISV
@@ -81,12 +82,13 @@ function formatTransactionStatus(transaction) {
81
82
  */
82
83
  export const getTransactionStatusTool = {
83
84
  name: "payware_operations_get_transaction_status",
85
+ annotations: READS,
84
86
  description: `Get status of an ACTIVE transaction by ID as an ISV on behalf of a merchant.
85
87
 
86
88
  **ISV Authentication:** Uses ISV JWT with merchant partner ID in 'aud' claim and OAuth2 token in 'sub' claim.
87
89
  **Endpoint:** GET /transactions/{transactionId}
88
90
  **Use Case:** Check status of ACTIVE transactions only. This endpoint only returns transactions with ACTIVE status.
89
- **Note:** For transactions with final statuses (CONFIRMED, DECLINED, FAILED, EXPIRED, CANCELLED), use 'payware_transactions_get_history' instead.
91
+ **Note:** For transactions with final statuses (CONFIRMED, DECLINED, FAILED, EXPIRED, CANCELLED), use 'payware_operations_get_transaction_history' instead.
90
92
 
91
93
  **Required:** Merchant Partner ID and OAuth2 token for ISV authentication.
92
94
 
@@ -3,6 +3,7 @@ import { createJWTForPartner } from '../../core/auth/jwt-factory.js';
3
3
  import { createMinimizedJSON } from '../../core/utils/json-serializer.js';
4
4
  import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
5
5
  import { describeApiError } from '../../shared/api-errors.js';
6
+ import { COMMITS } from '../../shared/tool-annotations.js';
6
7
 
7
8
  /**
8
9
  * Process a PEER transaction as an ISV on behalf of a merchant.
@@ -39,6 +40,7 @@ export async function processTransaction({
39
40
  paymentMethod,
40
41
  merchantPartnerId,
41
42
  oauth2Token,
43
+ idempotencyKey,
42
44
  useSandbox = true
43
45
  }) {
44
46
  if (!transactionId) {
@@ -108,13 +110,17 @@ export async function processTransaction({
108
110
  headers: {
109
111
  'Authorization': `Bearer ${jwtData.token}`,
110
112
  'Content-Type': 'application/json',
111
- 'Api-Version': '1'
113
+ 'Api-Version': '1',
114
+ ...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
112
115
  },
113
116
  // Tell axios to send the string as-is, don't serialize it again
114
117
  transformRequest: [(data) => data]
115
118
  });
116
119
 
117
- return response.data;
120
+ // A retry answered from the first call (Idempotency-Key) says so in a header, not in the body.
121
+ return response.headers?.['idempotent-replayed'] === 'true'
122
+ ? { ...response.data, replayed: true }
123
+ : response.data;
118
124
  } catch (error) {
119
125
  throw describeApiError(error, 'call the payware API');
120
126
  }
@@ -122,6 +128,7 @@ export async function processTransaction({
122
128
 
123
129
  export const processTransactionTool = {
124
130
  name: 'payware_operations_process_transaction',
131
+ annotations: COMMITS,
125
132
  description: `Process a PEER transaction as an ISV on behalf of a merchant - the merchant scanning a customer's QR or barcode to collect payment.
126
133
 
127
134
  **Endpoint:** POST /transactions/{transactionId}
@@ -146,6 +153,11 @@ payware returns on the response is the value to echo back at finalize, unchanged
146
153
  type: 'object',
147
154
  required: ['transactionId', 'amount', 'currency', 'reasonL1', 'merchantPartnerId', 'oauth2Token'],
148
155
  properties: {
156
+ idempotencyKey: {
157
+ type: "string",
158
+ description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
159
+ pattern: "^[\\x21-\\x7E]{1,255}$"
160
+ },
149
161
  transactionId: {
150
162
  type: 'string',
151
163
  description: "The customer's transaction to process, e.g. \"pw7e4rCToG\""
@@ -1,5 +1,6 @@
1
1
  import { getPartnerIdSafe } from '../../config/env.js';
2
2
  import { generateMockCallback, simulateCallbackDelivery } from '../../merchant/transactions/simulate-callback.js';
3
+ import { LOCAL } from '../../shared/tool-annotations.js';
3
4
 
4
5
  /**
5
6
  * Simulate the callback a merchant's endpoint receives, for an ISV building that handler.
@@ -17,6 +18,7 @@ import { generateMockCallback, simulateCallbackDelivery } from '../../merchant/t
17
18
  */
18
19
  export const simulateCallbackTool = {
19
20
  name: 'payware_operations_simulate_callback',
21
+ annotations: LOCAL,
20
22
  description: `Simulate the callback payload payware sends to a merchant's callbackUrl, for building and testing a webhook handler as an ISV.
21
23
 
22
24
  **Local only - this makes no API call.** payware has no endpoint that triggers a callback on demand,