@payware/mcp-server 1.3.2 → 1.4.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 (93) 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 +10 -5
  18. package/src/isv/oauth2/obtain-token.js +9 -4
  19. package/src/isv/oauth2/token-helper.js +28 -26
  20. package/src/isv/poi/cancel-price.js +9 -2
  21. package/src/isv/poi/get-poi.js +4 -3
  22. package/src/isv/poi/get-qrcode.js +40 -9
  23. package/src/isv/poi/get-status.js +196 -168
  24. package/src/isv/poi/list-pois.js +6 -6
  25. package/src/isv/poi/set-price.js +40 -53
  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 +2 -0
  37. package/src/isv/transactions/get-status.js +3 -1
  38. package/src/isv/transactions/process-transaction.js +2 -0
  39. package/src/isv/transactions/simulate-callback.js +21 -10
  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 +3 -2
  63. package/src/merchant/transactions/create-transaction.js +3 -1
  64. package/src/merchant/transactions/get-status.js +4 -3
  65. package/src/merchant/transactions/process-transaction.js +5 -4
  66. package/src/merchant/transactions/simulate-callback.js +325 -313
  67. package/src/merchant/transactions/transaction-history.js +7 -6
  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 +4 -3
  72. package/src/payment-institution/transactions/finalize-transaction.js +6 -3
  73. package/src/payment-institution/transactions/get-transaction-history.js +8 -5
  74. package/src/payment-institution/transactions/get-transaction-status.js +16 -13
  75. package/src/payment-institution/transactions/process-pi-transaction.js +7 -6
  76. package/src/payment-institution/transactions/simulate-pi-callback.js +388 -375
  77. package/src/payment-institution/transactions/soundbite-transaction.js +6 -5
  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 +4 -1
  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 +17 -265
  86. package/src/utils/code-examples/common/auth-examples.js +1 -1
  87. package/src/utils/code-examples/isv/products.js +1 -1
  88. package/src/utils/code-examples/isv/transactions.js +1 -1
  89. package/src/utils/code-examples/merchant/transactions.js +1 -1
  90. package/src/utils/format-request.js +2 -0
  91. package/src/utils/json-formatter.js +2 -0
  92. package/src/utils/server-info.js +2 -0
  93. package/src/utils/code-examples.js +0 -646
@@ -3,6 +3,7 @@ import { createAuthHeaders } from '../auth-headers.js';
3
3
  import { apiErrorResult } from '../api-errors.js';
4
4
  import { createMinimizedJSON } from '../../core/utils/json-serializer.js';
5
5
  import { getSandboxUrl, getProductionUrl } from '../../config/env.js';
6
+ import { CREATES } from '../tool-annotations.js';
6
7
 
7
8
  /**
8
9
  * Creating POIs (Points of Interaction) - the physical payment points a payer scans.
@@ -206,6 +207,7 @@ export function buildCreatePOITool({ partnerType, resolveAuth }) {
206
207
 
207
208
  return {
208
209
  name: 'payware_poi_create',
210
+ annotations: CREATES,
209
211
  description: `Create a single POI (Point of Interaction) - a physical payment point a payer scans.
210
212
 
211
213
  **Endpoint:** POST /poi -> 201 Created
@@ -241,7 +243,7 @@ ${isIsv ? `
241
243
  },
242
244
  callbackUrl: {
243
245
  type: 'string',
244
- description: 'HTTPS URL for POI events. Must present a publicly-trusted TLS certificate and resolve to a public address.',
246
+ description: 'HTTPS URL for this POI\'s callbacks: poi.scanned (with the new transaction id), poi.expired (price not scanned) and the sale\'s TRANSACTION_FINALIZED (final status, with poiId). Signed by the ISV that set the price, otherwise the merchant. A POI without one sends no callbacks - there is no per-price callback URL. Must present a publicly-trusted TLS certificate and resolve to a public address.',
245
247
  format: 'uri'
246
248
  },
247
249
  useSandbox: {
@@ -296,6 +298,7 @@ export function buildCreatePOIBatchTool({ partnerType, resolveAuth }) {
296
298
 
297
299
  return {
298
300
  name: 'payware_poi_create_batch',
301
+ annotations: CREATES,
299
302
  description: `Create up to ${MAX_POI_BATCH_SIZE} POIs in a single **atomic** call - the tool for rolling out a terminal estate.
300
303
 
301
304
  **Endpoint:** POST /poi/batch -> 201 Created, returning \`{ created, pois: [...] }\`
@@ -802,35 +802,46 @@ export async function updateAudio({
802
802
  throw new Error('audioId is required');
803
803
  }
804
804
 
805
- const requestBody = {};
806
-
807
- if (title !== undefined) requestBody.title = title;
808
- if (newProductId !== undefined) requestBody.productId = newProductId;
805
+ // PATCH is metadata only. The server refuses a different productId there with
806
+ // ERR_AUDIO_REASSIGN_FORBIDDEN and moves an audio through POST .../{id}/transfer instead
807
+ // (AudioService.update), so a rename and a move are two calls. The rename goes first: if the move
808
+ // is then refused, the title the caller asked for is still applied.
809
+ const move = newProductId !== undefined && newProductId !== productId;
810
+ if (title === undefined && !move) {
811
+ throw new Error('Nothing to update: provide a title, or a newProductId different from productId');
812
+ }
809
813
 
810
- const minimizedBody = createMinimizedJSON(requestBody);
811
- const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody });
812
814
  const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
815
+ const audioUrl = `${baseUrl}/products/${productId}/audios/${audioId}`;
816
+
817
+ const send = async (method, url, requestBody, operation) => {
818
+ const minimizedBody = createMinimizedJSON(requestBody);
819
+ const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody });
820
+ try {
821
+ const response = await axios[method](url, minimizedBody, { headers });
822
+ return {
823
+ success: true,
824
+ data: response.data,
825
+ requestInfo: {
826
+ url,
827
+ method: method.toUpperCase(),
828
+ requestBody: minimizedBody,
829
+ statusCode: response.status
830
+ }
831
+ };
832
+ } catch (error) {
833
+ throw describeApiError(error, operation);
834
+ }
835
+ };
813
836
 
814
- try {
815
- const response = await axios.patch(
816
- `${baseUrl}/products/${productId}/audios/${audioId}`,
817
- minimizedBody,
818
- { headers }
819
- );
820
-
821
- return {
822
- success: true,
823
- data: response.data,
824
- requestInfo: {
825
- url: `${baseUrl}/products/${productId}/audios/${audioId}`,
826
- method: 'PATCH',
827
- requestBody: minimizedBody,
828
- statusCode: response.status
829
- }
830
- };
831
- } catch (error) {
832
- throw describeApiError(error, 'update audio');
837
+ let result;
838
+ if (title !== undefined) {
839
+ result = await send('patch', audioUrl, { title }, 'update audio');
840
+ }
841
+ if (move) {
842
+ result = await send('post', `${audioUrl}/transfer`, { targetProductId: newProductId }, 'transfer audio');
833
843
  }
844
+ return result;
834
845
  }
835
846
 
836
847
  /**
@@ -2,6 +2,7 @@ import axios from 'axios';
2
2
  import { createAuthHeaders } from '../auth-headers.js';
3
3
  import { apiErrorResult } from '../api-errors.js';
4
4
  import { getSandboxUrl, getProductionUrl } from '../../config/env.js';
5
+ import { READS } from '../tool-annotations.js';
5
6
 
6
7
  /**
7
8
  * Shops - the merchant outlets a transaction, product or POI belongs to.
@@ -48,6 +49,7 @@ export function buildListShopsTool({ partnerType, resolveAuth }) {
48
49
 
49
50
  return {
50
51
  name: 'payware_shops_list',
52
+ annotations: READS,
51
53
  description: `List the merchant outlets (shops) the caller can act on.
52
54
 
53
55
  **Endpoint:** GET /shops
@@ -0,0 +1,53 @@
1
+ /**
2
+ * MCP tool annotations, as the six combinations this server's tools actually fall into.
3
+ *
4
+ * Annotations are hints a client uses to decide how much to ask the user before running a tool: a
5
+ * read can run unattended, a destructive call should be confirmed, a non-idempotent one should not
6
+ * be retried blindly after a timeout. Every tool declares one of these as `annotations`, and
7
+ * tests/tool-contract.test.js fails on a tool that does not. tests/tool-routes.test.js checks the
8
+ * choice against the route the tool calls, so a GET cannot be declared destructive or a DELETE
9
+ * read-only.
10
+ *
11
+ * All four hints are always set. The protocol defaults are the cautious ones (not read-only,
12
+ * destructive, open world), so a tool that left them out would be presented as more dangerous than
13
+ * it is, and a directory that lists servers requires them to be explicit.
14
+ *
15
+ * "Open world" means the tool reaches the payware API, and through it real payers, merchants and
16
+ * money. The local tools - keys, tokens, code samples, formatting, callback simulation - do not.
17
+ */
18
+
19
+ /** Computes something locally and calls nothing. */
20
+ export const LOCAL = Object.freeze({
21
+ readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false
22
+ });
23
+
24
+ /** Reads from the payware API and changes nothing. */
25
+ export const READS = Object.freeze({
26
+ readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true
27
+ });
28
+
29
+ /**
30
+ * Adds something that a repeat call returns rather than adds again: a shareable link, which the
31
+ * server mints on first request and records on the transaction, or a downloaded file saved locally.
32
+ */
33
+ export const ADDS = Object.freeze({
34
+ readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true
35
+ });
36
+
37
+ /** Creates something new each time it is called: a transaction, a product, a report run. */
38
+ export const CREATES = Object.freeze({
39
+ readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true
40
+ });
41
+
42
+ /** Overwrites, cancels or deletes. Repeating it changes nothing further. */
43
+ export const CHANGES = Object.freeze({
44
+ readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true
45
+ });
46
+
47
+ /**
48
+ * Moves a payment forward irreversibly: processing it as the payer, or finalizing it as the
49
+ * institution. A retry after a timeout must not be automatic - the first call may have landed.
50
+ */
51
+ export const COMMITS = Object.freeze({
52
+ readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true
53
+ });
@@ -19,6 +19,7 @@
19
19
  import { CommonTemplates } from '../utils/code-examples/common/helpers.js';
20
20
  import { AuthGenerators } from '../utils/code-examples/common/auth-examples.js';
21
21
  import { createDeterministicJSON } from '../core/utils/json-serializer.js';
22
+ import { LOCAL } from '../shared/tool-annotations.js';
22
23
 
23
24
  /**
24
25
  * Advanced payware Code Generator
@@ -324,22 +325,21 @@ class AdvancedCodeGenerator {
324
325
  */
325
326
  generateAuthenticationExample(language, partnerType, options) {
326
327
  const AuthGen = AuthGenerators[language];
327
- if (AuthGen) {
328
- const generator = new AuthGen();
329
- const envTemplate = generator.getEnvironmentTemplate(partnerType, options);
330
- const depsTemplate = generator.getDependenciesTemplate(options);
331
- const authTemplate = generator.getAuthTemplate(partnerType, options);
332
-
333
- return this.wrapCompleteExample(
334
- `${envTemplate}\n\n${depsTemplate}\n\n${authTemplate}`,
335
- 'Authentication Setup',
336
- language,
337
- partnerType,
338
- options
339
- );
340
- } else {
341
- return this.generateBasicAuthExample(language, partnerType, options);
328
+ if (!AuthGen) {
329
+ throw new Error(`No authentication generator for language: ${language}`);
342
330
  }
331
+ const generator = new AuthGen();
332
+ const envTemplate = generator.getEnvironmentTemplate(partnerType, options);
333
+ const depsTemplate = generator.getDependenciesTemplate(options);
334
+ const authTemplate = generator.getAuthTemplate(partnerType, options);
335
+
336
+ return this.wrapCompleteExample(
337
+ `${envTemplate}\n\n${depsTemplate}\n\n${authTemplate}`,
338
+ 'Authentication Setup',
339
+ language,
340
+ partnerType,
341
+ options
342
+ );
343
343
  }
344
344
 
345
345
  /**
@@ -1455,256 +1455,6 @@ echo "✅ Request completed"`;
1455
1455
  return this.wrapCodeExample(code, opDef.description, 'bash', partnerType, options);
1456
1456
  }
1457
1457
 
1458
-
1459
- generateBasicAuthExample(language, partnerType, options) {
1460
- const { includeComments = true } = options;
1461
-
1462
- const authExamples = {
1463
- python: `${includeComments ? '# Basic Authentication Setup - Python' : ''}
1464
- import jwt
1465
- import json
1466
- import hashlib
1467
- import base64
1468
- from datetime import datetime, timezone
1469
-
1470
- def create_jwt_token(request_body=None):
1471
- ${includeComments ? '"""Create JWT token for payware API authentication"""' : ''}
1472
- partner_id = "YOUR_PARTNER_ID"
1473
- private_key = """-----BEGIN RSA PRIVATE KEY-----
1474
- YOUR_PRIVATE_KEY_HERE
1475
- -----END RSA PRIVATE KEY-----"""
1476
-
1477
- # Create content SHA-256 for request body
1478
- content_sha256 = ""
1479
- if request_body:
1480
- content_sha256 = base64.b64encode(hashlib.sha256(request_body.encode()).digest()).decode()
1481
-
1482
- # JWT payload
1483
- payload = {
1484
- "iss": partner_id,
1485
- "aud": "payware.eu",
1486
- "iat": int(datetime.now(timezone.utc).timestamp()),
1487
- "exp": int(datetime.now(timezone.utc).timestamp()) + 300,
1488
- "contentSha256": content_sha256
1489
- }
1490
-
1491
- # Create JWT token
1492
- token = jwt.encode(payload, private_key, algorithm="RS256")
1493
- return token
1494
-
1495
- ${includeComments ? '# Example usage' : ''}
1496
- token = create_jwt_token()
1497
- print(f"JWT Token: {token}")`,
1498
-
1499
- nodejs: `${includeComments ? '// Basic Authentication Setup - Node.js' : ''}
1500
- const jwt = require('jsonwebtoken');
1501
- const crypto = require('crypto');
1502
-
1503
- function createJWTToken(requestBody = null) {
1504
- /**
1505
- * Create JWT token for payware API authentication
1506
- */
1507
- const partnerId = "YOUR_PARTNER_ID";
1508
- const privateKey = \`-----BEGIN RSA PRIVATE KEY-----
1509
- YOUR_PRIVATE_KEY_HERE
1510
- -----END RSA PRIVATE KEY-----\`;
1511
-
1512
- ${includeComments ? '// Create content SHA-256' : ''} for request body
1513
- let contentSha256 = "";
1514
- if (requestBody) {
1515
- contentSha256 = crypto.createHash('sha256').update(requestBody).digest('base64');
1516
- }
1517
-
1518
- // JWT payload
1519
- const payload = {
1520
- iss: partnerId,
1521
- aud: "payware.eu",
1522
- iat: Math.floor(Date.now() / 1000),
1523
- exp: Math.floor(Date.now() / 1000) + 300,
1524
- contentSha256: contentSha256
1525
- };
1526
-
1527
- // Create JWT token
1528
- const token = jwt.sign(payload, privateKey, { algorithm: 'RS256' });
1529
- return token;
1530
- }
1531
-
1532
- ${includeComments ? '// Example usage' : ''}
1533
- const token = createJWTToken();
1534
- console.log(\`JWT Token: \${token}\`);`,
1535
-
1536
- java: `${includeComments ? '// Basic Authentication Setup - Java' : ''}
1537
- import io.jsonwebtoken.Jwts;
1538
- import io.jsonwebtoken.SignatureAlgorithm;
1539
- import java.security.PrivateKey;
1540
- import java.security.spec.PKCS8EncodedKeySpec;
1541
- import java.security.KeyFactory;
1542
- import java.util.Date;
1543
- import java.util.Map;
1544
- import java.util.HashMap;
1545
- import java.security.MessageDigest;
1546
- import java.util.Base64;
1547
-
1548
- public class PaywareAuth {
1549
-
1550
- private static String createJWTToken(String requestBody) {
1551
- try {
1552
- String partnerId = "YOUR_PARTNER_ID";
1553
- String privateKeyPEM = "-----BEGIN RSA PRIVATE KEY-----\\nYOUR_PRIVATE_KEY_HERE\\n-----END RSA PRIVATE KEY-----";
1554
-
1555
- ${includeComments ? '// Create content SHA-256' : ''}
1556
- String contentSha256 = "";
1557
- if (requestBody != null) {
1558
- MessageDigest md = MessageDigest.getInstance("SHA-256");
1559
- byte[] digest = md.digest(requestBody.getBytes());
1560
- contentSha256 = Base64.getEncoder().encodeToString(digest);
1561
- }
1562
-
1563
- // JWT payload
1564
- Map<String, Object> claims = new HashMap<>();
1565
- claims.put("iss", partnerId);
1566
- claims.put("aud", "payware.eu");
1567
- claims.put("iat", new Date().getTime() / 1000);
1568
- claims.put("exp", (new Date().getTime() / 1000) + 300);
1569
- claims.put("contentSha256", contentSha256);
1570
-
1571
- // Note: You'll need to implement private key loading
1572
- // PrivateKey privateKey = loadPrivateKey(privateKeyPEM);
1573
-
1574
- return "your-jwt-token"; // Placeholder - implement JWT creation
1575
-
1576
- } catch (Exception e) {
1577
- throw new RuntimeException("Failed to create JWT token", e);
1578
- }
1579
- }
1580
-
1581
- public static void main(String[] args) {
1582
- String token = createJWTToken(null);
1583
- System.out.println("JWT Token: " + token);
1584
- }
1585
- }`,
1586
-
1587
- csharp: `${includeComments ? '// Basic Authentication Setup - C#' : ''}
1588
- using System;
1589
- using System.Text;
1590
- using System.Security.Cryptography;
1591
- using Microsoft.IdentityModel.Tokens;
1592
- using System.IdentityModel.Tokens.Jwt;
1593
- using System.Security.Claims;
1594
-
1595
- public class PaywareAuth
1596
- {
1597
- private static string CreateJWTToken(string requestBody = null)
1598
- {
1599
- var partnerId = "YOUR_PARTNER_ID";
1600
- var privateKeyPEM = @"-----BEGIN RSA PRIVATE KEY-----
1601
- YOUR_PRIVATE_KEY_HERE
1602
- -----END RSA PRIVATE KEY-----";
1603
-
1604
- ${includeComments ? '// Create content SHA-256' : ''}
1605
- var contentSha256 = "";
1606
- if (!string.IsNullOrEmpty(requestBody))
1607
- {
1608
- using (var sha256 = SHA256.Create())
1609
- {
1610
- var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(requestBody));
1611
- contentSha256 = Convert.ToBase64String(hash);
1612
- }
1613
- }
1614
-
1615
- // JWT payload
1616
- var claims = new[]
1617
- {
1618
- new Claim("iss", partnerId),
1619
- new Claim("aud", "payware.eu"),
1620
- new Claim("iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer),
1621
- new Claim("exp", DateTimeOffset.UtcNow.AddMinutes(5).ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer),
1622
- new Claim("contentSha256", contentSha256)
1623
- };
1624
-
1625
- // Note: You'll need to implement RSA key loading
1626
- // var rsa = RSA.Create();
1627
- // rsa.ImportFromPem(privateKeyPEM);
1628
- // var key = new RsaSecurityKey(rsa);
1629
-
1630
- return "your-jwt-token"; // Placeholder - implement JWT creation
1631
- }
1632
-
1633
- public static void Main(string[] args)
1634
- {
1635
- var token = CreateJWTToken();
1636
- Console.WriteLine($"JWT Token: {token}");
1637
- }
1638
- }`,
1639
-
1640
- php: `${includeComments ? '<?php // Basic Authentication Setup - PHP' : '<?php'}
1641
- require_once 'vendor/autoload.php';
1642
- use Firebase\\JWT\\JWT;
1643
- use Firebase\\JWT\\Key;
1644
-
1645
- function createJWTToken($requestBody = null) {
1646
- $partnerId = "YOUR_PARTNER_ID";
1647
- $privateKey = "-----BEGIN RSA PRIVATE KEY-----
1648
- YOUR_PRIVATE_KEY_HERE
1649
- -----END RSA PRIVATE KEY-----";
1650
-
1651
- ${includeComments ? '// Create content SHA-256' : ''}
1652
- $contentSha256 = "";
1653
- if ($requestBody !== null) {
1654
- $contentSha256 = base64_encode(hash('sha256', $requestBody, true));
1655
- }
1656
-
1657
- // JWT payload
1658
- $payload = [
1659
- 'iss' => $partnerId,
1660
- 'aud' => 'payware.eu',
1661
- 'iat' => time(),
1662
- 'exp' => time() + 300,
1663
- 'contentSha256' => $contentSha256
1664
- ];
1665
-
1666
- // Create JWT token
1667
- $token = JWT::encode($payload, $privateKey, 'RS256');
1668
- return $token;
1669
- }
1670
-
1671
- ${includeComments ? '// Example usage' : ''}
1672
- $token = createJWTToken();
1673
- echo "JWT Token: " . $token . "\\n";
1674
- ?>`,
1675
-
1676
- curl: `${includeComments ? '#!/bin/bash\n# Basic Authentication Setup - cURL' : '#!/bin/bash'}
1677
-
1678
- # Configuration
1679
- PARTNER_ID="YOUR_PARTNER_ID"
1680
- PRIVATE_KEY_FILE="path/to/private-key.pem"
1681
-
1682
- # Function to create JWT token (simplified)
1683
- create_jwt_token() {
1684
- local request_body="\$1"
1685
- local content_sha256=""
1686
-
1687
- if [ -n "\$request_body" ]; then
1688
- content_sha256=\$(echo -n "\$request_body" | openssl dgst -sha256 -binary | base64)
1689
- fi
1690
-
1691
- echo "your-jwt-token" # Placeholder - implement JWT creation with openssl
1692
- }
1693
-
1694
- ${includeComments ? '# Example usage' : ''}
1695
- JWT_TOKEN=\$(create_jwt_token)
1696
- echo "JWT Token: \$JWT_TOKEN"`
1697
- };
1698
-
1699
- return this.wrapCodeExample(
1700
- authExamples[language] || authExamples.python,
1701
- 'Authentication Setup',
1702
- language,
1703
- partnerType,
1704
- options
1705
- );
1706
- }
1707
-
1708
1458
  // Helper methods for Java code generation
1709
1459
  toPascalCase(str) {
1710
1460
  return str.split(/[-_]/).map(word =>
@@ -1986,6 +1736,7 @@ export const advancedCodeGenerator = new AdvancedCodeGenerator();
1986
1736
  */
1987
1737
  export const generateCodeExampleTool = {
1988
1738
  name: 'payware_generate_code_example',
1739
+ annotations: LOCAL,
1989
1740
  description: 'Generate production-ready payware API integration code examples with authentication, error handling, and environment configuration for any operation across 16 supported operations and 6 programming languages.',
1990
1741
 
1991
1742
  inputSchema: {
@@ -2126,6 +1877,7 @@ Use different parameters to explore all available options!
2126
1877
  */
2127
1878
  export const generateDocumentationTool = {
2128
1879
  name: 'payware_generate_documentation',
1880
+ annotations: LOCAL,
2129
1881
  description: 'Generate comprehensive documentation for payware API integration with quick start instructions, authentication flows, operation examples, error handling patterns, and language-specific integration guides.',
2130
1882
 
2131
1883
  inputSchema: {
@@ -68,7 +68,7 @@ from cryptography.hazmat.primitives import serialization`;
68
68
  ${options.includeComments ? '# Create JWT payload\n ' : ''}payload = {
69
69
  'iss': partner_id,
70
70
  'aud': 'https://payware.eu',
71
- 'iat': int(datetime.utcnow().timestamp())
71
+ 'iat': int(datetime.now().timestamp())
72
72
  }
73
73
 
74
74
  ${options.includeComments ? '# Create and return token\n ' : ''}token = jwt.encode(payload, private_key, algorithm='RS256', headers=header)
@@ -295,7 +295,7 @@ def create_isv_jwt_token(merchant_partner_id, oauth2_token, request_body=None, u
295
295
  'iss': isv_partner_id, # ISV Partner ID
296
296
  'aud': merchant_partner_id, # Target Merchant ID
297
297
  'sub': oauth2_token, # OAuth2 access token
298
- 'iat': int(datetime.utcnow().timestamp())
298
+ 'iat': int(datetime.now().timestamp())
299
299
  }
300
300
 
301
301
  # Create and return token
@@ -217,7 +217,7 @@ def create_isv_jwt_token(merchant_partner_id, oauth2_token, request_body=None, u
217
217
  'iss': config['isv_partner_id'], # ISV Partner ID
218
218
  'aud': merchant_partner_id, # Target Merchant ID
219
219
  'sub': oauth2_token, # OAuth2 access token
220
- 'iat': int(datetime.utcnow().timestamp())
220
+ 'iat': int(datetime.now().timestamp())
221
221
  }
222
222
 
223
223
  # Create token
@@ -171,7 +171,7 @@ def create_jwt_token(request_body=None, use_sandbox=True):
171
171
  payload = {
172
172
  'iss': config['partner_id'],
173
173
  'aud': 'https://payware.eu',
174
- 'iat': int(datetime.utcnow().timestamp())
174
+ 'iat': int(datetime.now().timestamp())
175
175
  }
176
176
 
177
177
  # Create token
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import { createMinimizedJSON } from '../core/utils/json-serializer.js';
6
+ import { LOCAL } from '../shared/tool-annotations.js';
6
7
 
7
8
  /**
8
9
  * Format transaction request data
@@ -165,6 +166,7 @@ export function formatCurlCommand(method, endpoint, headers, body = null) {
165
166
  */
166
167
  export const formatRequestTool = {
167
168
  name: "payware_utils_format_request",
169
+ annotations: LOCAL,
168
170
  description: "Format and validate payware API requests with proper structure and headers",
169
171
  inputSchema: {
170
172
  type: "object",
@@ -5,12 +5,14 @@
5
5
 
6
6
  import { createDeterministicJSON, validateJSONConsistency } from '../core/utils/json-serializer.js';
7
7
  import { generateContentSha256 } from '../core/auth/jwt-token.js';
8
+ import { LOCAL } from '../shared/tool-annotations.js';
8
9
 
9
10
  /**
10
11
  * Format JSON with deterministic serialization tool
11
12
  */
12
13
  export const formatJSONDeterministicTool = {
13
14
  name: "payware_utils_format_json_deterministic",
15
+ annotations: LOCAL,
14
16
  description: "Format JSON payload with deterministic key sorting for consistent SHA-256 calculation and payware API compliance",
15
17
  inputSchema: {
16
18
  type: "object",
@@ -5,12 +5,14 @@
5
5
  import { readFileSync } from 'fs';
6
6
  import { getPartnerTypeSafe, getSandboxUrl, getProductionUrl } from '../config/env.js';
7
7
  import { getPartnerDisplayInfo, getPartnerConfig } from '../config/partner-types.js';
8
+ import { LOCAL } from '../shared/tool-annotations.js';
8
9
 
9
10
  /**
10
11
  * Get server information tool implementation
11
12
  */
12
13
  export const getServerInfoTool = {
13
14
  name: "payware_utils_server_info",
15
+ annotations: LOCAL,
14
16
  description: "Get MCP server version, status, and environment information",
15
17
  inputSchema: {
16
18
  type: "object",