@atbas/m-mcp 0.1.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 (366) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +364 -0
  3. package/dist/builder/transaction-builder.d.ts +53 -0
  4. package/dist/builder/transaction-builder.d.ts.map +1 -0
  5. package/dist/builder/transaction-builder.js +159 -0
  6. package/dist/builder/transaction-builder.js.map +1 -0
  7. package/dist/catalogue/default-catalogue.d.ts +18 -0
  8. package/dist/catalogue/default-catalogue.d.ts.map +1 -0
  9. package/dist/catalogue/default-catalogue.js +21 -0
  10. package/dist/catalogue/default-catalogue.js.map +1 -0
  11. package/dist/catalogue/endpoints.d.ts +22 -0
  12. package/dist/catalogue/endpoints.d.ts.map +1 -0
  13. package/dist/catalogue/endpoints.js +24 -0
  14. package/dist/catalogue/endpoints.js.map +1 -0
  15. package/dist/catalogue/flows.d.ts +32 -0
  16. package/dist/catalogue/flows.d.ts.map +1 -0
  17. package/dist/catalogue/flows.js +64 -0
  18. package/dist/catalogue/flows.js.map +1 -0
  19. package/dist/catalogue/hash-options.d.ts +112 -0
  20. package/dist/catalogue/hash-options.d.ts.map +1 -0
  21. package/dist/catalogue/hash-options.js +151 -0
  22. package/dist/catalogue/hash-options.js.map +1 -0
  23. package/dist/catalogue/types.d.ts +279 -0
  24. package/dist/catalogue/types.d.ts.map +1 -0
  25. package/dist/catalogue/types.js +360 -0
  26. package/dist/catalogue/types.js.map +1 -0
  27. package/dist/codegen/generate.d.ts +14 -0
  28. package/dist/codegen/generate.d.ts.map +1 -0
  29. package/dist/codegen/generate.js +490 -0
  30. package/dist/codegen/generate.js.map +1 -0
  31. package/dist/codegen/languages/node.d.ts +3 -0
  32. package/dist/codegen/languages/node.d.ts.map +1 -0
  33. package/dist/codegen/languages/node.js +32 -0
  34. package/dist/codegen/languages/node.js.map +1 -0
  35. package/dist/codegen/languages/php.d.ts +3 -0
  36. package/dist/codegen/languages/php.d.ts.map +1 -0
  37. package/dist/codegen/languages/php.js +27 -0
  38. package/dist/codegen/languages/php.js.map +1 -0
  39. package/dist/codegen/languages/python.d.ts +3 -0
  40. package/dist/codegen/languages/python.d.ts.map +1 -0
  41. package/dist/codegen/languages/python.js +27 -0
  42. package/dist/codegen/languages/python.js.map +1 -0
  43. package/dist/codegen/renderer.d.ts +24 -0
  44. package/dist/codegen/renderer.d.ts.map +1 -0
  45. package/dist/codegen/renderer.js +59 -0
  46. package/dist/codegen/renderer.js.map +1 -0
  47. package/dist/codegen/types.d.ts +50 -0
  48. package/dist/codegen/types.d.ts.map +1 -0
  49. package/dist/codegen/types.js +5 -0
  50. package/dist/codegen/types.js.map +1 -0
  51. package/dist/config/credentials.d.ts +64 -0
  52. package/dist/config/credentials.d.ts.map +1 -0
  53. package/dist/config/credentials.js +216 -0
  54. package/dist/config/credentials.js.map +1 -0
  55. package/dist/config/environment.d.ts +23 -0
  56. package/dist/config/environment.d.ts.map +1 -0
  57. package/dist/config/environment.js +54 -0
  58. package/dist/config/environment.js.map +1 -0
  59. package/dist/core/dependencies.d.ts +43 -0
  60. package/dist/core/dependencies.d.ts.map +1 -0
  61. package/dist/core/dependencies.js +2 -0
  62. package/dist/core/dependencies.js.map +1 -0
  63. package/dist/core/registry.d.ts +33 -0
  64. package/dist/core/registry.d.ts.map +1 -0
  65. package/dist/core/registry.js +13 -0
  66. package/dist/core/registry.js.map +1 -0
  67. package/dist/core/server.d.ts +61 -0
  68. package/dist/core/server.d.ts.map +1 -0
  69. package/dist/core/server.js +90 -0
  70. package/dist/core/server.js.map +1 -0
  71. package/dist/dependencies.d.ts +28 -0
  72. package/dist/dependencies.d.ts.map +1 -0
  73. package/dist/dependencies.js +2 -0
  74. package/dist/dependencies.js.map +1 -0
  75. package/dist/diagnostics/diagnose.d.ts +43 -0
  76. package/dist/diagnostics/diagnose.d.ts.map +1 -0
  77. package/dist/diagnostics/diagnose.js +121 -0
  78. package/dist/diagnostics/diagnose.js.map +1 -0
  79. package/dist/domain/amount.d.ts +157 -0
  80. package/dist/domain/amount.d.ts.map +1 -0
  81. package/dist/domain/amount.js +275 -0
  82. package/dist/domain/amount.js.map +1 -0
  83. package/dist/domain/datetime.d.ts +95 -0
  84. package/dist/domain/datetime.d.ts.map +1 -0
  85. package/dist/domain/datetime.js +211 -0
  86. package/dist/domain/datetime.js.map +1 -0
  87. package/dist/domain/response-codes.d.ts +116 -0
  88. package/dist/domain/response-codes.d.ts.map +1 -0
  89. package/dist/domain/response-codes.js +380 -0
  90. package/dist/domain/response-codes.js.map +1 -0
  91. package/dist/domain/secure-hash.d.ts +78 -0
  92. package/dist/domain/secure-hash.d.ts.map +1 -0
  93. package/dist/domain/secure-hash.js +69 -0
  94. package/dist/domain/secure-hash.js.map +1 -0
  95. package/dist/domain/signature/jazzcash.d.ts +56 -0
  96. package/dist/domain/signature/jazzcash.d.ts.map +1 -0
  97. package/dist/domain/signature/jazzcash.js +214 -0
  98. package/dist/domain/signature/jazzcash.js.map +1 -0
  99. package/dist/domain/signature/registry.d.ts +69 -0
  100. package/dist/domain/signature/registry.d.ts.map +1 -0
  101. package/dist/domain/signature/registry.js +92 -0
  102. package/dist/domain/signature/registry.js.map +1 -0
  103. package/dist/domain/signature/scheme.d.ts +349 -0
  104. package/dist/domain/signature/scheme.d.ts.map +1 -0
  105. package/dist/domain/signature/scheme.js +398 -0
  106. package/dist/domain/signature/scheme.js.map +1 -0
  107. package/dist/domain/txn-ref.d.ts +76 -0
  108. package/dist/domain/txn-ref.d.ts.map +1 -0
  109. package/dist/domain/txn-ref.js +126 -0
  110. package/dist/domain/txn-ref.js.map +1 -0
  111. package/dist/domain/types.d.ts +45 -0
  112. package/dist/domain/types.d.ts.map +1 -0
  113. package/dist/domain/types.js +70 -0
  114. package/dist/domain/types.js.map +1 -0
  115. package/dist/errors.d.ts +84 -0
  116. package/dist/errors.d.ts.map +1 -0
  117. package/dist/errors.js +87 -0
  118. package/dist/errors.js.map +1 -0
  119. package/dist/gateway/checkout-form.d.ts +16 -0
  120. package/dist/gateway/checkout-form.d.ts.map +1 -0
  121. package/dist/gateway/checkout-form.js +103 -0
  122. package/dist/gateway/checkout-form.js.map +1 -0
  123. package/dist/gateway/checkout-output.d.ts +70 -0
  124. package/dist/gateway/checkout-output.d.ts.map +1 -0
  125. package/dist/gateway/checkout-output.js +199 -0
  126. package/dist/gateway/checkout-output.js.map +1 -0
  127. package/dist/gateway/guards.d.ts +37 -0
  128. package/dist/gateway/guards.d.ts.map +1 -0
  129. package/dist/gateway/guards.js +44 -0
  130. package/dist/gateway/guards.js.map +1 -0
  131. package/dist/gateway/http-client.d.ts +42 -0
  132. package/dist/gateway/http-client.d.ts.map +1 -0
  133. package/dist/gateway/http-client.js +153 -0
  134. package/dist/gateway/http-client.js.map +1 -0
  135. package/dist/gateway/rest-client.d.ts +42 -0
  136. package/dist/gateway/rest-client.d.ts.map +1 -0
  137. package/dist/gateway/rest-client.js +241 -0
  138. package/dist/gateway/rest-client.js.map +1 -0
  139. package/dist/gateway/transport.d.ts +31 -0
  140. package/dist/gateway/transport.d.ts.map +1 -0
  141. package/dist/gateway/transport.js +73 -0
  142. package/dist/gateway/transport.js.map +1 -0
  143. package/dist/index.d.ts +3 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +75 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/install/cli.d.ts +38 -0
  148. package/dist/install/cli.d.ts.map +1 -0
  149. package/dist/install/cli.js +274 -0
  150. package/dist/install/cli.js.map +1 -0
  151. package/dist/install/harnesses.d.ts +74 -0
  152. package/dist/install/harnesses.d.ts.map +1 -0
  153. package/dist/install/harnesses.js +263 -0
  154. package/dist/install/harnesses.js.map +1 -0
  155. package/dist/knowledge/corpus.d.ts +15 -0
  156. package/dist/knowledge/corpus.d.ts.map +1 -0
  157. package/dist/knowledge/corpus.js +129 -0
  158. package/dist/knowledge/corpus.js.map +1 -0
  159. package/dist/knowledge/search.d.ts +29 -0
  160. package/dist/knowledge/search.d.ts.map +1 -0
  161. package/dist/knowledge/search.js +181 -0
  162. package/dist/knowledge/search.js.map +1 -0
  163. package/dist/knowledge/source.d.ts +60 -0
  164. package/dist/knowledge/source.d.ts.map +1 -0
  165. package/dist/knowledge/source.js +91 -0
  166. package/dist/knowledge/source.js.map +1 -0
  167. package/dist/knowledge/types.d.ts +40 -0
  168. package/dist/knowledge/types.d.ts.map +1 -0
  169. package/dist/knowledge/types.js +19 -0
  170. package/dist/knowledge/types.js.map +1 -0
  171. package/dist/paths.d.ts +26 -0
  172. package/dist/paths.d.ts.map +1 -0
  173. package/dist/paths.js +106 -0
  174. package/dist/paths.js.map +1 -0
  175. package/dist/prompts/integration-walkthrough.d.ts +11 -0
  176. package/dist/prompts/integration-walkthrough.d.ts.map +1 -0
  177. package/dist/prompts/integration-walkthrough.js +52 -0
  178. package/dist/prompts/integration-walkthrough.js.map +1 -0
  179. package/dist/prompts/register.d.ts +4 -0
  180. package/dist/prompts/register.d.ts.map +1 -0
  181. package/dist/prompts/register.js +4 -0
  182. package/dist/prompts/register.js.map +1 -0
  183. package/dist/registry.d.ts +14 -0
  184. package/dist/registry.d.ts.map +1 -0
  185. package/dist/registry.js +2 -0
  186. package/dist/registry.js.map +1 -0
  187. package/dist/resources/knowledge-resources.d.ts +5 -0
  188. package/dist/resources/knowledge-resources.d.ts.map +1 -0
  189. package/dist/resources/knowledge-resources.js +121 -0
  190. package/dist/resources/knowledge-resources.js.map +1 -0
  191. package/dist/resources/register.d.ts +4 -0
  192. package/dist/resources/register.d.ts.map +1 -0
  193. package/dist/resources/register.js +8 -0
  194. package/dist/resources/register.js.map +1 -0
  195. package/dist/server.d.ts +40 -0
  196. package/dist/server.d.ts.map +1 -0
  197. package/dist/server.js +56 -0
  198. package/dist/server.js.map +1 -0
  199. package/dist/telemetry/logger.d.ts +31 -0
  200. package/dist/telemetry/logger.d.ts.map +1 -0
  201. package/dist/telemetry/logger.js +67 -0
  202. package/dist/telemetry/logger.js.map +1 -0
  203. package/dist/telemetry/redaction.d.ts +88 -0
  204. package/dist/telemetry/redaction.d.ts.map +1 -0
  205. package/dist/telemetry/redaction.js +238 -0
  206. package/dist/telemetry/redaction.js.map +1 -0
  207. package/dist/tools/build-transaction-parameters.d.ts +10 -0
  208. package/dist/tools/build-transaction-parameters.d.ts.map +1 -0
  209. package/dist/tools/build-transaction-parameters.js +154 -0
  210. package/dist/tools/build-transaction-parameters.js.map +1 -0
  211. package/dist/tools/call-context.d.ts +47 -0
  212. package/dist/tools/call-context.d.ts.map +1 -0
  213. package/dist/tools/call-context.js +15 -0
  214. package/dist/tools/call-context.js.map +1 -0
  215. package/dist/tools/codegen-tools.d.ts +4 -0
  216. package/dist/tools/codegen-tools.d.ts.map +1 -0
  217. package/dist/tools/codegen-tools.js +131 -0
  218. package/dist/tools/codegen-tools.js.map +1 -0
  219. package/dist/tools/credential-tools.d.ts +32 -0
  220. package/dist/tools/credential-tools.d.ts.map +1 -0
  221. package/dist/tools/credential-tools.js +65 -0
  222. package/dist/tools/credential-tools.js.map +1 -0
  223. package/dist/tools/descriptor.d.ts +52 -0
  224. package/dist/tools/descriptor.d.ts.map +1 -0
  225. package/dist/tools/descriptor.js +2 -0
  226. package/dist/tools/descriptor.js.map +1 -0
  227. package/dist/tools/diagnostic-tools.d.ts +3 -0
  228. package/dist/tools/diagnostic-tools.d.ts.map +1 -0
  229. package/dist/tools/diagnostic-tools.js +128 -0
  230. package/dist/tools/diagnostic-tools.js.map +1 -0
  231. package/dist/tools/gateway-tools.d.ts +6 -0
  232. package/dist/tools/gateway-tools.d.ts.map +1 -0
  233. package/dist/tools/gateway-tools.js +381 -0
  234. package/dist/tools/gateway-tools.js.map +1 -0
  235. package/dist/tools/hash-tools.d.ts +5 -0
  236. package/dist/tools/hash-tools.d.ts.map +1 -0
  237. package/dist/tools/hash-tools.js +238 -0
  238. package/dist/tools/hash-tools.js.map +1 -0
  239. package/dist/tools/knowledge-tools.d.ts +7 -0
  240. package/dist/tools/knowledge-tools.d.ts.map +1 -0
  241. package/dist/tools/knowledge-tools.js +247 -0
  242. package/dist/tools/knowledge-tools.js.map +1 -0
  243. package/dist/tools/onboarding-checklist.d.ts +3 -0
  244. package/dist/tools/onboarding-checklist.d.ts.map +1 -0
  245. package/dist/tools/onboarding-checklist.js +141 -0
  246. package/dist/tools/onboarding-checklist.js.map +1 -0
  247. package/dist/tools/register.d.ts +60 -0
  248. package/dist/tools/register.d.ts.map +1 -0
  249. package/dist/tools/register.js +145 -0
  250. package/dist/tools/register.js.map +1 -0
  251. package/dist/tools/tool-kit.d.ts +88 -0
  252. package/dist/tools/tool-kit.d.ts.map +1 -0
  253. package/dist/tools/tool-kit.js +297 -0
  254. package/dist/tools/tool-kit.js.map +1 -0
  255. package/dist/validation/payload-validator.d.ts +29 -0
  256. package/dist/validation/payload-validator.d.ts.map +1 -0
  257. package/dist/validation/payload-validator.js +79 -0
  258. package/dist/validation/payload-validator.js.map +1 -0
  259. package/dist/validation/rules/amount.d.ts +3 -0
  260. package/dist/validation/rules/amount.d.ts.map +1 -0
  261. package/dist/validation/rules/amount.js +77 -0
  262. package/dist/validation/rules/amount.js.map +1 -0
  263. package/dist/validation/rules/bill-reference.d.ts +10 -0
  264. package/dist/validation/rules/bill-reference.d.ts.map +1 -0
  265. package/dist/validation/rules/bill-reference.js +34 -0
  266. package/dist/validation/rules/bill-reference.js.map +1 -0
  267. package/dist/validation/rules/cnic.d.ts +3 -0
  268. package/dist/validation/rules/cnic.d.ts.map +1 -0
  269. package/dist/validation/rules/cnic.js +42 -0
  270. package/dist/validation/rules/cnic.js.map +1 -0
  271. package/dist/validation/rules/constants.d.ts +9 -0
  272. package/dist/validation/rules/constants.d.ts.map +1 -0
  273. package/dist/validation/rules/constants.js +28 -0
  274. package/dist/validation/rules/constants.js.map +1 -0
  275. package/dist/validation/rules/constraints.d.ts +3 -0
  276. package/dist/validation/rules/constraints.d.ts.map +1 -0
  277. package/dist/validation/rules/constraints.js +113 -0
  278. package/dist/validation/rules/constraints.js.map +1 -0
  279. package/dist/validation/rules/datetime.d.ts +3 -0
  280. package/dist/validation/rules/datetime.d.ts.map +1 -0
  281. package/dist/validation/rules/datetime.js +49 -0
  282. package/dist/validation/rules/datetime.js.map +1 -0
  283. package/dist/validation/rules/empty-string.d.ts +13 -0
  284. package/dist/validation/rules/empty-string.d.ts.map +1 -0
  285. package/dist/validation/rules/empty-string.js +32 -0
  286. package/dist/validation/rules/empty-string.js.map +1 -0
  287. package/dist/validation/rules/expiry.d.ts +3 -0
  288. package/dist/validation/rules/expiry.d.ts.map +1 -0
  289. package/dist/validation/rules/expiry.js +52 -0
  290. package/dist/validation/rules/expiry.js.map +1 -0
  291. package/dist/validation/rules/msisdn.d.ts +3 -0
  292. package/dist/validation/rules/msisdn.d.ts.map +1 -0
  293. package/dist/validation/rules/msisdn.js +45 -0
  294. package/dist/validation/rules/msisdn.js.map +1 -0
  295. package/dist/validation/rules/presence.d.ts +3 -0
  296. package/dist/validation/rules/presence.d.ts.map +1 -0
  297. package/dist/validation/rules/presence.js +90 -0
  298. package/dist/validation/rules/presence.js.map +1 -0
  299. package/dist/validation/rules/return-url.d.ts +14 -0
  300. package/dist/validation/rules/return-url.d.ts.map +1 -0
  301. package/dist/validation/rules/return-url.js +58 -0
  302. package/dist/validation/rules/return-url.js.map +1 -0
  303. package/dist/validation/rules/tool-argument.d.ts +16 -0
  304. package/dist/validation/rules/tool-argument.d.ts.map +1 -0
  305. package/dist/validation/rules/tool-argument.js +38 -0
  306. package/dist/validation/rules/tool-argument.js.map +1 -0
  307. package/dist/validation/rules/txn-ref.d.ts +3 -0
  308. package/dist/validation/rules/txn-ref.d.ts.map +1 -0
  309. package/dist/validation/rules/txn-ref.js +47 -0
  310. package/dist/validation/rules/txn-ref.js.map +1 -0
  311. package/dist/validation/rules/unknown-fields.d.ts +10 -0
  312. package/dist/validation/rules/unknown-fields.d.ts.map +1 -0
  313. package/dist/validation/rules/unknown-fields.js +29 -0
  314. package/dist/validation/rules/unknown-fields.js.map +1 -0
  315. package/dist/validation/types.d.ts +36 -0
  316. package/dist/validation/types.d.ts.map +1 -0
  317. package/dist/validation/types.js +12 -0
  318. package/dist/validation/types.js.map +1 -0
  319. package/dist/version.d.ts +23 -0
  320. package/dist/version.d.ts.map +1 -0
  321. package/dist/version.js +23 -0
  322. package/dist/version.js.map +1 -0
  323. package/knowledge/diagnostics/symptoms.json +321 -0
  324. package/knowledge/docs/bnpl-guide.md +77 -0
  325. package/knowledge/docs/card-page-redirection.md +67 -0
  326. package/knowledge/docs/card-refund.md +91 -0
  327. package/knowledge/docs/hmac-sha256-calculation.md +72 -0
  328. package/knowledge/docs/index.json +189 -0
  329. package/knowledge/docs/ipn-implementation.md +89 -0
  330. package/knowledge/docs/mwallet-recurring.md +117 -0
  331. package/knowledge/docs/mwallet-refund.md +65 -0
  332. package/knowledge/docs/mwallet-rest-v1-1.md +126 -0
  333. package/knowledge/docs/mwallet-rest-v2-0-cnic.md +113 -0
  334. package/knowledge/docs/portal-guide.md +45 -0
  335. package/knowledge/docs/shopify-guide.md +74 -0
  336. package/knowledge/docs/status-inquiry-2025-26.md +32 -0
  337. package/knowledge/docs/status-inquiry.md +111 -0
  338. package/knowledge/docs/wordpress-guide.md +49 -0
  339. package/knowledge/flow.schema.json +390 -0
  340. package/knowledge/flows/bnpl-page-redirection-v1.1.json +211 -0
  341. package/knowledge/flows/card-page-redirection-v1.1.json +211 -0
  342. package/knowledge/flows/mwallet-rest-v1.1.json +187 -0
  343. package/knowledge/flows/mwallet-rest-v2.0-cnic.json +197 -0
  344. package/knowledge/flows/mwallet-token-pay-v4.0.json +130 -0
  345. package/knowledge/flows/refund-bnpl.json +105 -0
  346. package/knowledge/flows/refund-card-v1.1.json +112 -0
  347. package/knowledge/flows/refund-card-v2.0.json +121 -0
  348. package/knowledge/flows/refund-mwallet-v1.1.json +106 -0
  349. package/knowledge/flows/status-inquiry-v1.1.json +102 -0
  350. package/knowledge/flows/status-inquiry-v2.0.json +103 -0
  351. package/knowledge/flows/token-delete-v1.json +85 -0
  352. package/knowledge/flows/token-inquiry-v1.json +85 -0
  353. package/knowledge/flows/wallet-linking-portal.json +103 -0
  354. package/knowledge/templates/node/checkout-redirect.tmpl +166 -0
  355. package/knowledge/templates/node/ipn-handler.tmpl +108 -0
  356. package/knowledge/templates/node/rest-client.tmpl +197 -0
  357. package/knowledge/templates/node/wallet-linking.tmpl +147 -0
  358. package/knowledge/templates/php/checkout-redirect.tmpl +149 -0
  359. package/knowledge/templates/php/ipn-handler.tmpl +105 -0
  360. package/knowledge/templates/php/rest-client.tmpl +191 -0
  361. package/knowledge/templates/php/wallet-linking.tmpl +137 -0
  362. package/knowledge/templates/python/checkout-redirect.tmpl +148 -0
  363. package/knowledge/templates/python/ipn-handler.tmpl +110 -0
  364. package/knowledge/templates/python/rest-client.tmpl +179 -0
  365. package/knowledge/templates/python/wallet-linking.tmpl +133 -0
  366. package/package.json +84 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eren Atbas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,364 @@
1
+ # JazzCash MCP Integration Server
2
+
3
+ An MCP server that performs JazzCash payment-gateway integrations inside a merchant's own AI tooling — Claude Desktop, Claude Code, Cursor, or any other MCP client.
4
+
5
+ ## The problem
6
+
7
+ Merchant onboarding at JazzCash depends on two resident engineers, one seat vacant, walking every merchant's developer through the same hosted checkout, the same credentials, the same hash generation, the same return URLs, the same sandbox tests. Go-live speed is capped by engineer hours rather than by how ready the merchant is, and the knowledge leaves with the people.
8
+
9
+ This server encodes what those engineers know so the merchant's own AI can do the integration: look up the official guidance, generate correct code, validate parameters and secure hashes, run sandbox transactions, and diagnose failures — while the engineers keep the parts that need judgement.
10
+
11
+ > **Status:** Phase 1 pilot — documentation lookup, code generation and sandbox validation. The merchant-dashboard assistant is a later phase and is not built here.
12
+
13
+ ## What is in this repository
14
+
15
+ Three deliverables share this tree, because they share one definition of what each tool does and where it is allowed to run.
16
+
17
+ **The MCP server** is the repository root, package `@atbas/m-mcp`, and is what the rest of this README describes. A merchant installs it in their own AI tooling, it answers from the corpus in `knowledge/`, and it reports to nobody. Neither project below changes its behaviour or its safety model.
18
+
19
+ **`dashboard/`** is a Next.js admin console that also hosts the credential-free half of the tool surface over HTTP. It creates merchants, mints and revokes scoped access tokens, applies rate limits and quotas, and records what each token called — method, tool, outcome and duration, never arguments and never results. It holds no merchant credential of any kind: the four tools that need one are not part of the hosted surface at all, and the server it builds is constructed from an explicit environment carrying no `JAZZCASH_*` value, so those tools could not authenticate even if something asked them to. It is the operator's console for this project, not the merchant-portal assistant the status note above refers to. Its root path is the merchant-facing install guide — the one page it serves to somebody with no session — and the console proper sits behind the operator sign-in at `/admin`.
20
+
21
+ **`connector/`** is `@atbas/m-mcp-connector`, the package a merchant installs in place of the bare server to reach the hosted tier, which is live. The four credential-requiring tools run locally from it, against the merchant's own environment, so no password, Integrity Salt or MPIN leaves their machine; everything else is proxied to the hosted endpoint under their token. With no token, or with that endpoint unreachable, the local half keeps working. It is licensed MIT and is released from `github.com/eatbas/m-mcp-connector`, a mirror generated from this tree; this repository stays the only place any of it is edited. **No version of it is on npm yet** — the package is built and its release procedure is written down, and neither has been run; [`docs/mcp/PUBLISHING.md`](docs/mcp/PUBLISHING.md) records what remains.
22
+
23
+ The MCP server is what most of this README documents. [The hosted tier](#the-hosted-tier) below covers how the three fit together, how an operator deploys the dashboard and the endpoint, and how a merchant reaches them; [`docs/mcp/HOSTED.md`](docs/mcp/HOSTED.md) is that tier's threat model and operating manual. Once the connector is released, it is a merchant's whole install: one line, and they never see this repository at all.
24
+
25
+ ## Safety first
26
+
27
+ Sandbox and production share **identical gateway URLs** in every official JazzCash guide. The environment is a property of the _credentials_, not the endpoint.
28
+
29
+ - Every network tool requires an explicit `environment` argument.
30
+ - Production money movement requires **both** `JAZZCASH_ALLOW_LIVE=true` in the server environment **and** `confirmLiveEnvironment: true` on the call.
31
+ - Money-moving calls are never retried automatically.
32
+ - Credentials are scrubbed from every tool result, both text and structured output.
33
+
34
+ Read [`docs/mcp/SAFETY.md`](docs/mcp/SAFETY.md) before pointing this at production.
35
+
36
+ ## What it knows
37
+
38
+ The knowledge corpus is transcribed from the fourteen 2026 JazzCash merchant guides in `docs/integration_documents/`, covering **14 integration flows**: card and BNPL hosted checkout, MWallet REST v1.1 and v2.0, token payment, wallet linking, token inquiry and delete, Status Inquiry v1.1 and v2.0, and four refund variants — plus IPN, the merchant portal, WooCommerce and Shopify.
39
+
40
+ It also encodes the places those guides contradict themselves, because those are where merchants get stuck. Among them: the official PHP sample silently drops a value of integer `0` from the hash; the wallet-linking sample publishes the Integrity Salt in browser JavaScript; card and BNPL refunds return unprefixed response fields; the MWallet v2.0 sample sets an expiry two days out while the same page says one; the token payment sample sets an expiry two months _before_ its transaction. All are recorded, tested against, and corrected in generated code.
41
+
42
+ Open questions raised by this work are collected in [`docs/mcp/JAZZCASH-CLARIFICATIONS.md`](docs/mcp/JAZZCASH-CLARIFICATIONS.md) for the acquiring team.
43
+
44
+ ## Install
45
+
46
+ ### For merchants — once published
47
+
48
+ ```bash
49
+ npx -y @atbas/m-mcp # nothing to clone, nothing to build
50
+ ```
51
+
52
+ Or register it directly with your AI tool and let the tool fetch it:
53
+
54
+ ```json
55
+ { "mcpServers": { "m-mcp": { "command": "npx", "args": ["-y", "@atbas/m-mcp"] } } }
56
+ ```
57
+
58
+ `npx` keeps merchants on the current corpus automatically, which matters because JazzCash reissues these guides yearly.
59
+
60
+ > **Not yet published.** Nothing is on npm under either name: `npm view jazzcash-mcp` returned a 404 on 2026-08-23, and the package was renamed to `@atbas/m-mcp` later the same day without a version ever being published under it — so neither command above resolves anything today. What was holding it is settled: redistribution of the transcribed corpus was authorised by the product director on 2026-08-23 (assumption A7), the licence decision is MIT, and `package.json` now carries that licence and no `"private"` key. `npm pack` works and the tarball has been verified end to end; [`docs/mcp/PUBLISHING.md`](docs/mcp/PUBLISHING.md) lists the steps that remain, and the one question — trademark — that is still JazzCash's to answer.
61
+
62
+ ### From this repository
63
+
64
+ Repository development requires Node.js 24.18.0 or newer and npm 11.16.0. The project records both constraints in `.nvmrc` and `package.json`.
65
+
66
+ ```bash
67
+ npm ci
68
+ npm approve-scripts --allow-scripts-pending # must report no unreviewed scripts
69
+ npm run deploy # pick your harness interactively
70
+ ```
71
+
72
+ The clean install fails closed if a dependency adds an unreviewed lifecycle script. `package.json` approves only the reviewed, exact `esbuild` version and explicitly denies the platform-inapplicable `fsevents` script.
73
+
74
+ `npm run deploy` builds, detects the AI harnesses on your machine and registers the server with the ones you choose. Supported: **Claude Code**, **OpenAI Codex** and **Antigravity**.
75
+
76
+ ```bash
77
+ npm run deploy:list # what is detected, what is installed
78
+ npm run deploy -- --all # every detected harness
79
+ npm run deploy -- --target=claude,codex
80
+ npm run deploy -- --dry-run --all # show the changes without writing
81
+ npm run deploy -- --remove --all # uninstall
82
+ ```
83
+
84
+ Every write preserves the rest of the config file — your other MCP servers, their `env` blocks and your settings are untouched — and leaves a timestamped backup beside it. That backup is a full copy, so it may contain credentials from any server in the file; it is created owner-only and is never pruned, so delete old ones once you no longer need them.
85
+
86
+ Then restart the harness.
87
+
88
+ ## Credentials
89
+
90
+ **13 of the 17 tools need no credentials at all.** Documentation lookup, code generation, secure-hash construction and verification, payload validation and diagnosis all work the moment the server is installed. This is an _integration_ server: its job is to teach, generate and check, none of which touches your merchant account.
91
+
92
+ Four tools call the gateway and do need them: `build_transaction_parameters`, `send_gateway_request`, `run_sandbox_smoke_test`, `build_checkout_form`. The hash tools additionally accept an `integritySalt` argument per call, so a merchant debugging a mismatch configures nothing at all.
93
+
94
+ When you do need them, use either:
95
+
96
+ **1. Your harness's own `env` block** — the standard MCP mechanism:
97
+
98
+ ```json
99
+ {
100
+ "mcpServers": {
101
+ "m-mcp": {
102
+ "command": "npx",
103
+ "args": ["-y", "@atbas/m-mcp"],
104
+ "env": {
105
+ "JAZZCASH_SANDBOX_MERCHANT_ID": "MC12345",
106
+ "JAZZCASH_SANDBOX_PASSWORD": "…",
107
+ "JAZZCASH_SANDBOX_INTEGRITY_SALT": "…",
108
+ "JAZZCASH_SANDBOX_RETURN_URL": "https://shop.example.pk/jazzcash/return"
109
+ }
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ **2. `JAZZCASH_CREDENTIALS_FILE`** pointing at a JSON file kept outside any repository — preferable where the harness config itself is committed.
116
+
117
+ ### The server does not read a `.env`, deliberately
118
+
119
+ An IDE spawns an MCP server with the **merchant's workspace** as its working directory. A dotenv loader would therefore read the merchant's _own application_ `.env` — which, for a WooCommerce or Node merchant, very plausibly holds `JAZZCASH_MERCHANT_ID` and `JAZZCASH_INTEGRITY_SALT` for their live site.
120
+
121
+ The server would then silently adopt production credentials that nobody decided to give it. Since sandbox and production share endpoints, which environment is in play must always be an explicit decision, never a side effect of where the process happened to start. So there is no `.env` support and no `.env.example`.
122
+
123
+ ## Using it
124
+
125
+ The intended entry points are the prompt and one tool:
126
+
127
+ - **`jazzcash_integration_walkthrough`** — a guided prompt that sequences the whole integration.
128
+ - **`jazzcash_build_transaction_parameters`** — assembles a complete payload from business data alone: constants filled, timestamps in Pakistan Standard Time, amount converted to minor units, references generated, payload validated, and `pp_SecureHash` computed last from exactly the map it returns.
129
+
130
+ A typical session:
131
+
132
+ ```
133
+ "Add JazzCash mobile wallet payments to my checkout."
134
+ → jazzcash_list_integration_flows pick a flow
135
+ → jazzcash_get_onboarding_checklist what to do in the portal first
136
+ → jazzcash_generate_integration_code working PHP, Node or Python
137
+ → jazzcash_generate_ipn_handler the mandatory listener
138
+ → jazzcash_run_sandbox_smoke_test prove it end to end (sandbox only)
139
+
140
+ "I'm getting HASH_MISMATCH."
141
+ → jazzcash_verify_secure_hash replays 13 known-wrong constructions
142
+ against your own parameters and reports
143
+ which one reproduces your hash
144
+ ```
145
+
146
+ That last point is the difference between this and a documentation search: when a hash is wrong, the server does not guess. It executes the known construction errors against the merchant's actual payload, and when one reproduces their hash, the cause is demonstrated rather than suggested.
147
+
148
+ ## The hosted tier
149
+
150
+ The other two deliverables in this tree exist so that a merchant can be given metered, revocable access to the tooling without anybody having to hand over a credential. This section is the operator's and the merchant's route in; [`docs/mcp/HOSTED.md`](docs/mcp/HOSTED.md) is the threat model behind it, and [`docs/mcp/STAGING.md`](docs/mcp/STAGING.md) is how to stand a disposable copy of it up locally and prove the whole loop before a merchant sees it.
151
+
152
+ ### How the three pieces fit
153
+
154
+ ```
155
+ AI client (Claude Code, Claude Desktop, Cursor, Codex, Antigravity)
156
+ │ stdio
157
+
158
+ connector/ the merchant's own machine
159
+ ├── local the 4 credential-requiring tools, from the merchant's own
160
+ │ environment — no password, Integrity Salt or MPIN leaves it
161
+ └── remote HTTPS POST /api/mcp
162
+ Authorization: Bearer mmcp_xxxxxxxx_…
163
+
164
+
165
+ dashboard/ the operator's VPS
166
+ per-address limit → token → scope → per-token limit and quota
167
+ → the 13 credential-free tools
168
+ → one usage row per JSON-RPC entry: method, tool, outcome, duration
169
+ ```
170
+
171
+ All three read one definition of which tool is which. Every tool has a descriptor — name, group, providers it can serve, and whether it needs a credential — and the dashboard and the connector import those descriptors rather than keeping their own copies, because a copy is what drifts. They are declared in two modules on purpose: the four credential-requiring ones in `src/tools/credential-tools.ts`, which the connector imports on its own so that its build never reaches the corpus loader or the code generators, and the rest in `src/tools/register.ts`, which imports that narrow module and re-exports it so the full surface is still one list. A tool added without a descriptor fails `tests/tools/register.test.ts`.
172
+
173
+ A merchant who is not using the hosted tier is unaffected by any of this: the stdio server described above serves all seventeen tools locally and reports to nobody.
174
+
175
+ ### Deploying it — for an operator
176
+
177
+ The dashboard is a standalone project with its own lockfile under `dashboard/`, deliberately not an npm workspace, so the publishable root package's dependency tree stays free of a web framework's.
178
+
179
+ Locally, with Docker:
180
+
181
+ ```bash
182
+ cp dashboard/.env.example dashboard/.env # then fill it in; it is gitignored
183
+ ./start.sh # rebuild the image, start it, wait for healthy
184
+ curl -sS http://localhost:3100/api/health
185
+ ```
186
+
187
+ [`start.sh`](start.sh) is a wrapper around `docker compose --file docker-compose.yml` and nothing more: it rebuilds from the working tree with the layer cache intact, waits for the healthcheck rather than returning the moment the container is _started_, and prints the entrypoint's own refusal when it will not serve. `./start.sh down` stops the stack and leaves the `m_mcp_data` volume — the database — alone; `./start.sh help` lists the rest. Plain `docker compose up --build` remains equivalent for the start itself. Note that the container publishes the port `npm run dev` uses, so the two cannot run at once.
188
+
189
+ Every `*_HMAC_SECRET` wants 32 characters or more — `openssl rand -base64 48` — and `EMAIL_API_TOKEN` comes from the mail service's operator and is never invented. Note that `docker compose config` resolves and prints every value in `dashboard/.env` in clear text; validate the file with it if you must, but never paste that output anywhere.
190
+
191
+ On Coolify, the deployment file is [`docker-compose.coolify.yml`](docker-compose.coolify.yml), whose header lists every variable the operator sets in Coolify's own UI and explains each of the four ways it differs from the local file. **It must never be run with the plain `docker compose` CLI** — only `docker-compose.yml` is a supported local entry point. The three HMAC secrets and the mail token exist only in Coolify's UI: never in a file in this repository, never as a build argument.
192
+
193
+ Whichever path, the container's entrypoint asserts before it serves anything:
194
+
195
+ - **no `JAZZCASH_*` variable is present** — the hosted tier holds no merchant credential, and a variable that suggests otherwise stops the boot rather than being silently ignored;
196
+ - **`/app/data` is writable by the unprivileged user**, so the database lands on the named volume rather than on a container layer the next redeploy destroys;
197
+ - then it runs the migrations and the idempotent seed, and only then starts the server.
198
+
199
+ Once it serves, two paths matter to a human. `https://m-mcp.atbas.xyz/` is the merchant-facing install guide — how a merchant installs the connector, and the only page served without a session — and `https://m-mcp.atbas.xyz/admin` is the operator sign-in, with the console itself at `/admin/overview` behind it. Locally the same two are `http://localhost:3100/` and `http://localhost:3100/admin`. Everything a machine talks to is `/api/mcp`.
200
+
201
+ There is no self-registration. The seed creates the single operator account from `ADMIN_USERNAME`, `ADMIN_PASSWORD`, `ADMIN_EMAIL` and `ADMIN_DISPLAY_NAME`, and signing in needs that password **and** a one-time code sent to `ADMIN_EMAIL` through `mail-api.atbas.xyz`. That account is what creates merchants and mints their access tokens: a minted token is displayed exactly once and stored only as a keyed hash, so a lost token is replaced rather than recovered, and revoking one stops the very next call it makes.
202
+
203
+ One recurring job completes the deployment: `npm run purge` in `dashboard/`, once a day, as a Coolify scheduled task or a cron entry. It deletes raw usage rows past `USAGE_RETENTION_DAYS` and never touches the daily rollups. `npm run purge -- --dry-run` reports what would go.
204
+
205
+ ### Reaching it — for a merchant
206
+
207
+ Two ways in, and they are not equivalent.
208
+
209
+ **The connector** gives both halves: the four credential-requiring tools running locally against your own environment, and everything else proxied to the hosted endpoint under your token. It is `@atbas/m-mcp-connector`, and once it is released to npm — it is not there yet — the whole of it is one entry in your AI client's configuration:
210
+
211
+ ```json
212
+ { "mcpServers": { "m-mcp": { "command": "npx", "args": ["-y", "@atbas/m-mcp-connector"] } } }
213
+ ```
214
+
215
+ Nothing to clone and nothing to build. The package carries the 14 flow specifications its local tools read and inlines the credential half of this server, so it resolves neither `@atbas/m-mcp` nor the transcribed corpus that [`docs/mcp/PUBLISHING.md`](docs/mcp/PUBLISHING.md) covers. [`connector/README.md`](connector/README.md) is the authority on what it does and how it is configured, and the install guide at `https://m-mcp.atbas.xyz/` is written from that file — where the two differ, the file is right. Supply the token as `M_MCP_TOKEN` in your AI client's `env` block rather than as a command-line flag, because every argument a process was started with is readable by anything else on the machine.
216
+
217
+ **A direct HTTP registration** gives the hosted half only, for AI clients that speak Streamable HTTP themselves:
218
+
219
+ ```json
220
+ {
221
+ "mcpServers": {
222
+ "m-mcp": {
223
+ "type": "http",
224
+ "url": "https://m-mcp.atbas.xyz/api/mcp",
225
+ "headers": { "Authorization": "Bearer mmcp_xxxxxxxx_…" }
226
+ }
227
+ }
228
+ }
229
+ ```
230
+
231
+ That route serves the thirteen credential-free tools your token's scope allows, and never the four that need a credential — those exist only where your credentials are.
232
+
233
+ **Register exactly one of these.** The stdio server above, the connector, and this HTTP entry are three ways of reaching the same product, so every snippet in this file keys them `m-mcp` — which is the server's own name, and what `npm run deploy` writes. They are alternatives rather than layers: pasting two of them into one configuration file leaves you with whichever came last, silently, because they share that key. Pick the row that matches how you want the credential tools to run, and use only that one.
234
+
235
+ | You want | Register | Credential tools run |
236
+ | -------------------------------------------------- | --------------------------------------- | ----------------------------- |
237
+ | Everything local, your own credentials, no account | the stdio server, `@atbas/m-mcp` | on your machine |
238
+ | Both halves, metered under a token | the connector, `@atbas/m-mcp-connector` | on your machine |
239
+ | The hosted half only, no local process | this HTTP entry | nowhere — they are not served |
240
+
241
+ To check a token by hand:
242
+
243
+ ```bash
244
+ curl -sS -X POST https://m-mcp.atbas.xyz/api/mcp \
245
+ -H 'Authorization: Bearer mmcp_xxxxxxxx_…' \
246
+ -H 'Content-Type: application/json' \
247
+ -H 'Accept: application/json, text/event-stream' \
248
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
249
+ ```
250
+
251
+ `401` means the token was not accepted, `403` that it is revoked, expired or its merchant deactivated, and `429` that an allowance was reached — honour the `Retry-After` header. [`docs/mcp/HOSTED.md`](docs/mcp/HOSTED.md) says what to do about each, what the endpoint records about your calls, and what it deliberately never records.
252
+
253
+ ## Development
254
+
255
+ | Command | Purpose |
256
+ | -------------------------- | ---------------------------------------------------------------------------------------------------- |
257
+ | `npm run typecheck` | Type-check without emitting |
258
+ | `npm run lint` | ESLint, including the stdout and floating-promise guards |
259
+ | `npm run format:check` | Prettier check |
260
+ | `npm test` | Full suite |
261
+ | `npm run test:fast` | Domain, validation, catalogue and config tests only — the quickest useful signal |
262
+ | `npm run test:changed` | Tests related to changed files |
263
+ | `npm run test:coverage` | Full suite with coverage, which is where the per-file thresholds bite |
264
+ | `npm run build` | Emit `dist/` |
265
+ | `npm run pack:check` | Build, then `npm pack --dry-run` — proves `knowledge/` is still in the tarball |
266
+ | `npm run scan:credentials` | Refuse third-party credential literals and unreviewed binaries under `docs/` (see below) |
267
+ | `npm run release:check` | Every gate above in one chain, plus the interpreter guards. What CI runs and what `npm publish` runs |
268
+ | `npm run extract-pdf-text` | Regenerate plain-text extractions of the source PDFs (requires poppler) |
269
+
270
+ `release:check` is a gate, not a survey: it opens with the credential scan and the PHP and Python guards, and **fails when either interpreter is missing or older than the version CI installs** (PHP 8.3, Python 3.12). That is deliberate. `npm test` skips the cross-language checks when an interpreter is absent, which is the right behaviour for a quick local run; a release must not be able to pass with the parity checks quietly skipped.
271
+
272
+ ### Continuous integration
273
+
274
+ `.github/workflows/ci.yml` runs `release:check` on every push and pull request, with PHP and Python installed first and every action pinned to a commit SHA.
275
+
276
+ It needs one repository secret, **`CREDENTIAL_PATTERNS`**: an extended-regular-expression alternation of the third-party credential literals that must never reach this corpus. The values are credentials, so they live in the secret and nowhere in the repository. The job sets `CREDENTIAL_PATTERNS_REQUIRED`, so **an unset or empty secret fails the build** rather than reporting a scan that never ran.
277
+
278
+ Locally the secret is absent, so `npm run scan:credentials` reports that phase as skipped — never as clean — and still enforces the second phase, which fails on any new or changed binary artefact under `docs/`. That phase exists because the literal scan reads text only, and the vendor PDFs are exactly where cleartext credentials would hide.
279
+
280
+ ### Architecture
281
+
282
+ ```
283
+ src/
284
+ domain/ secure hash, money, Pakistan-time stamps, references, response codes
285
+ catalogue/ flow specifications loaded from knowledge/flows/*.json
286
+ validation/ one rule per file, composed by payload-validator.ts
287
+ builder/ assemble + validate + sign a payload
288
+ knowledge/ documentation corpus and offline BM25 search
289
+ codegen/ templates bound to flow specifications
290
+ gateway/ guards, HTTP transport, REST execution, checkout form
291
+ diagnostics/ symptom knowledge base
292
+ tools/ one MCP tool per file
293
+ knowledge/ the data: flows, docs, templates, diagnostics
294
+ ```
295
+
296
+ Two properties are worth preserving if you extend this:
297
+
298
+ - **The corpus is data, not code.** Flow specifications, documentation, templates and diagnostics all live in `knowledge/`. A correction from JazzCash should be a data change.
299
+ - **Citations are tested.** Every `docRef` on every flow, and every reference in the diagnostics base, is asserted to resolve to a real document _and_ section. An anchor on a heading too deep to be addressable fails at load rather than producing a dead link.
300
+
301
+ ### Testing notes
302
+
303
+ No test reaches the JazzCash gateway. `tests/helpers/stub-gateway.ts` is a local HTTP server, and the production guard is separately asserted to fire before any request is recorded.
304
+
305
+ `src/domain/secure-hash.ts`, `src/domain/amount.ts`, `src/gateway/guards.ts` and `src/telemetry/redaction.ts` are held at 100 % statement, branch, function and line coverage by per-file thresholds in `vitest.config.ts` — the run fails, not warns, if that regresses.
306
+
307
+ Generated PHP is syntax-checked with `php -l` and generated Python with `python -m py_compile`. Under `npm test` those checks skip cleanly when the interpreter is absent. Under `npm run release:check` and `npm publish` they cannot: `scripts/require-php.mjs` and `scripts/require-python.mjs` fail the run outright when the interpreter is missing or older than the version CI installs, because a release that skipped the cross-language HMAC parity checks would be indistinguishable from one that passed them.
308
+
309
+ ### SDK version
310
+
311
+ Built against `@modelcontextprotocol/sdk` v1.30 using `registerTool` / `registerResource` / `registerPrompt` with v1 raw-shape `inputSchema`. The v2 line replaces raw shapes with `z.object(...)`; when migrating, the SDK surface is confined to `src/core/registry.ts`, which declares the registration signature over `McpServer` and `applyRegistrars` — `src/registry.ts` no longer names the SDK at all, and does nothing but parameterise that signature for the full dependency set — together with the `src/tools`, `src/resources` and `src/prompts` modules.
312
+
313
+ ### The dashboard is held on an unsupported ESLint, deliberately
314
+
315
+ The root and `connector/` are on ESLint 10. `dashboard/` is on **9.39.5**, which npm now marks
316
+ deprecated — _"This version is no longer supported."_ That is not an oversight and not a preference.
317
+
318
+ Three plugins reached through `eslint-config-next` still cap their `eslint` peer range at 9, and
319
+ each is already at its newest published release:
320
+
321
+ | Plugin | Latest | Peer range |
322
+ | ------------------------ | ------ | ------------- |
323
+ | `eslint-plugin-import` | 2.32.0 | `… \|\| ^9` |
324
+ | `eslint-plugin-jsx-a11y` | 6.10.2 | `… \|\| ^9` |
325
+ | `eslint-plugin-react` | 7.37.5 | `… \|\| ^9.7` |
326
+
327
+ `eslint-config-next` itself declares the permissive `eslint: >=9.0.0`, so the conflict only surfaces
328
+ one level down. Forcing it with `--legacy-peer-deps` is the wrong move: an overridden peer conflict
329
+ in a lint toolchain fails at rule-load time with an error naming neither the plugin nor the cause,
330
+ and the lint then covers less than it appears to.
331
+
332
+ **Re-check trigger:** whenever `eslint-config-next` is bumped, run
333
+
334
+ ```bash
335
+ npm view eslint-plugin-import peerDependencies.eslint
336
+ npm view eslint-plugin-jsx-a11y peerDependencies.eslint
337
+ npm view eslint-plugin-react peerDependencies.eslint
338
+ ```
339
+
340
+ and move the dashboard to ESLint 10 the moment all three admit `^10`. Expect the three rules
341
+ `eslint:recommended` gained in v10 — `no-unassigned-vars`, `no-useless-assignment` and
342
+ `preserve-caught-error` — to fire; fix them rather than disabling them. The root and the connector
343
+ already pass all three.
344
+
345
+ ### `@types/node` tracks the floor, not the latest
346
+
347
+ Each project pins `@types/node` to the major matching its own `engines.node`, and **not** to the
348
+ newest published. The root and the dashboard are on `^24`, matching `.nvmrc`, CI and the
349
+ `node:24-bookworm-slim` image the dashboard deploys on; `connector/` is on `^20`, matching the
350
+ `>=20.19.0` floor it declares so that merchants on Node 20 and 22 LTS are supported.
351
+
352
+ Bumping any of them to the latest major would let the compiler admit an API the supported runtime
353
+ does not have — a failure no test here catches, because the tests run on Node 24. The connector is
354
+ the one that matters: it is the package merchants install, and `npx` runs it on whatever they have.
355
+ Its typecheck against Node 20 types is therefore a real check of its own advertised floor, and it
356
+ passes.
357
+
358
+ When a project's `engines.node` moves, move its `@types/node` in the same change. Not before.
359
+
360
+ ## Licence
361
+
362
+ **MIT**, decided on 2026-08-23 alongside the same day's authorisation of the corpus for redistribution and sale (assumption A7), and carried in `package.json` since. The knowledge corpus is derived from JazzCash merchant guides: MIT covers this repository's own work and makes no claim over JazzCash's documentation, specifications or marks. The use of the mark itself is the one part of item 13 in [`docs/mcp/JAZZCASH-CLARIFICATIONS.md`](docs/mcp/JAZZCASH-CLARIFICATIONS.md) that no decision here can answer, and it is still open.
363
+
364
+ `connector/` carries the same licence. `@atbas/m-mcp-connector` is MIT, © 2026 Eren Atbas: it ships the 14 flow specifications and the credential half of this server, and none of the transcribed documents, the templates or the diagnostics base. [`docs/mcp/PUBLISHING.md`](docs/mcp/PUBLISHING.md) records exactly what that package and its public mirror each carry, what stays here, and the steps neither package has been through — as of 2026-08-23, neither is on npm.
@@ -0,0 +1,53 @@
1
+ import { type CredentialProfile } from '../config/credentials.js';
2
+ import type { IntegrationFlow } from '../catalogue/types.js';
3
+ import { type HashStringBreakdown } from '../domain/secure-hash.js';
4
+ import type { NormalisedParameters } from '../domain/types.js';
5
+ import { type ValidationResult } from '../validation/payload-validator.js';
6
+ /**
7
+ * Assemble a complete, valid, signed payload for a flow.
8
+ *
9
+ * This is the highest-value entry point in the server: it removes the whole
10
+ * class of errors that come from hand-assembling payloads — a missing constant,
11
+ * a host-timezone timestamp, an amount in major units, an omitted empty field,
12
+ * a stale hash. The caller supplies business data; everything else is derived
13
+ * from the flow specification and the credential profile.
14
+ */
15
+ export interface TransactionInput {
16
+ /** Amount in major units, e.g. "100.00" or 100. Converted to minor units. */
17
+ readonly amount?: string | number | undefined;
18
+ /** Amount already in minor units, e.g. "10000". Takes precedence over `amount`. */
19
+ readonly amountMinorUnits?: string | undefined;
20
+ readonly billReference?: string | undefined;
21
+ readonly description?: string | undefined;
22
+ readonly txnRefNo?: string | undefined;
23
+ readonly requestId?: string | undefined;
24
+ /** Up to three alphanumeric characters prefixed to generated references. */
25
+ readonly referencePrefix?: string | undefined;
26
+ /** Flow-specific fields: pp_MobileNumber, pp_CNIC, pp_MSISDN, pp_PaymentToken, ppmpf_3… */
27
+ readonly extras?: Readonly<Record<string, string>> | undefined;
28
+ /** Days between the transaction time and its expiry. Defaults to the documented 1. */
29
+ readonly expiryDays?: number | undefined;
30
+ readonly now?: Date | undefined;
31
+ }
32
+ export interface BuiltTransaction {
33
+ readonly flowId: string;
34
+ /** Complete payload including the flow's own signature field, ready to transmit. */
35
+ readonly parameters: NormalisedParameters;
36
+ readonly secureHash: string;
37
+ readonly hashBreakdown: HashStringBreakdown;
38
+ readonly validation: ValidationResult;
39
+ /** Values this builder derived rather than receiving, for transparency. */
40
+ readonly generated: Readonly<Record<string, string>>;
41
+ }
42
+ /**
43
+ * Build and sign a payload.
44
+ *
45
+ * The payload is validated before it is hashed, and the hash is computed last,
46
+ * from exactly the map that will be transmitted, so the two can never disagree.
47
+ * An invalid payload is still returned, unsigned, with its validation result:
48
+ * the caller needs to see what is wrong, not just that something is.
49
+ */
50
+ export declare function buildTransaction(flow: IntegrationFlow, input: TransactionInput, profile: CredentialProfile, integritySalt?: string): BuiltTransaction;
51
+ /** Throwing variant, for callers that cannot proceed with an invalid payload. */
52
+ export declare function buildTransactionOrThrow(flow: IntegrationFlow, input: TransactionInput, profile: CredentialProfile, integritySalt?: string): BuiltTransaction;
53
+ //# sourceMappingURL=transaction-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-builder.d.ts","sourceRoot":"","sources":["../../src/builder/transaction-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE5F,OAAO,KAAK,EAAiB,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAsC,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAExG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAE5F;;;;;;;;GAQG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC9C,mFAAmF;IACnF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAC/D,sFAAsF;IACtF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oFAAoF;IACpF,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACtD;AA0HD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,iBAAiB,EAC1B,aAAa,GAAE,MAA8B,GAC5C,gBAAgB,CAsDlB;AAED,iFAAiF;AACjF,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,iBAAiB,EAC1B,aAAa,GAAE,MAA8B,GAC5C,gBAAgB,CASlB"}
@@ -0,0 +1,159 @@
1
+ import { credentialParameterValue } from '../config/credentials.js';
2
+ import { requestHashOptions, signatureFieldName } from '../catalogue/hash-options.js';
3
+ import { toMinorUnits } from '../domain/amount.js';
4
+ import { formatTxnDateTime, txnExpiryDateTime } from '../domain/datetime.js';
5
+ import { buildHashString, computeSecureHash } from '../domain/secure-hash.js';
6
+ import { generateBillReference, generateRequestId, generateTxnRefNo } from '../domain/txn-ref.js';
7
+ import { JazzCashValidationError } from '../errors.js';
8
+ import { validatePayload } from '../validation/payload-validator.js';
9
+ function resolveAmount(input) {
10
+ if (input.amountMinorUnits !== undefined && input.amountMinorUnits !== '') {
11
+ return input.amountMinorUnits;
12
+ }
13
+ if (input.amount === undefined || input.amount === '') {
14
+ return undefined;
15
+ }
16
+ return toMinorUnits(input.amount);
17
+ }
18
+ /**
19
+ * Values fixed by the specification or by the credential profile.
20
+ *
21
+ * Returns `undefined` when this parameter is not one the flow or the profile
22
+ * decides, leaving it to {@link deriveGeneratedValue}.
23
+ */
24
+ function resolveDeclaredValue(parameter, flow, input, profile) {
25
+ const extra = input.extras?.[parameter.name];
26
+ if (extra !== undefined) {
27
+ return extra;
28
+ }
29
+ // "No parameters may be added or removed from the request payload." An
30
+ // optional field may carry a value, but its key must still be transmitted, so
31
+ // an unsupplied optional field defaults to the empty string rather than being
32
+ // dropped.
33
+ if (parameter.requirement === 'must-be-empty' || parameter.requirement === 'optional') {
34
+ return '';
35
+ }
36
+ if (parameter.valueType === 'constant') {
37
+ return parameter.constantValue ?? flow.constants[parameter.name];
38
+ }
39
+ return credentialParameterValue(parameter.name, profile);
40
+ }
41
+ /**
42
+ * Values this builder computes: amounts, references and timestamps.
43
+ *
44
+ * Anything generated rather than supplied is recorded in `generated`, so the
45
+ * caller can see what was chosen for them.
46
+ */
47
+ function deriveGeneratedValue(parameter, input, now, generated) {
48
+ const prefixOption = input.referencePrefix === undefined ? {} : { prefix: input.referencePrefix };
49
+ const remember = (value) => {
50
+ generated[parameter.name] = value;
51
+ return value;
52
+ };
53
+ switch (parameter.valueType) {
54
+ case 'minor-units':
55
+ return resolveAmount(input);
56
+ case 'bill-reference':
57
+ return input.billReference !== undefined && input.billReference !== ''
58
+ ? input.billReference
59
+ : remember(generateBillReference({ now, ...prefixOption }));
60
+ case 'txn-ref':
61
+ return input.txnRefNo !== undefined && input.txnRefNo !== ''
62
+ ? input.txnRefNo
63
+ : remember(generateTxnRefNo({ now, ...prefixOption }));
64
+ case 'request-id':
65
+ return input.requestId !== undefined && input.requestId !== ''
66
+ ? input.requestId
67
+ : remember(generateRequestId({ now, ...prefixOption }));
68
+ case 'pkt-datetime':
69
+ return remember(formatTxnDateTime(now));
70
+ case 'pkt-expiry':
71
+ return remember(txnExpiryDateTime(now, input.expiryDays ?? 1));
72
+ case 'string':
73
+ return parameter.name === 'pp_Description' ? input.description : undefined;
74
+ // Flow-specific values the caller must supply through `extras`.
75
+ case 'constant':
76
+ case 'url':
77
+ case 'msisdn':
78
+ case 'cnic':
79
+ case 'payment-token':
80
+ case 'secure-hash':
81
+ return undefined;
82
+ }
83
+ }
84
+ /**
85
+ * Derive the value for one declared parameter.
86
+ *
87
+ * Returns `undefined` when the value cannot be derived, leaving the field absent
88
+ * so that validation reports it with a message naming what to supply. Silently
89
+ * substituting a placeholder would send a wrong value to a payment gateway.
90
+ */
91
+ function deriveValue(parameter, flow, input, profile, now, generated) {
92
+ return (resolveDeclaredValue(parameter, flow, input, profile) ?? deriveGeneratedValue(parameter, input, now, generated));
93
+ }
94
+ /**
95
+ * Build and sign a payload.
96
+ *
97
+ * The payload is validated before it is hashed, and the hash is computed last,
98
+ * from exactly the map that will be transmitted, so the two can never disagree.
99
+ * An invalid payload is still returned, unsigned, with its validation result:
100
+ * the caller needs to see what is wrong, not just that something is.
101
+ */
102
+ export function buildTransaction(flow, input, profile, integritySalt = profile.integritySalt) {
103
+ const now = input.now ?? new Date();
104
+ const generated = {};
105
+ const parameters = {};
106
+ for (const parameter of flow.parameters) {
107
+ if (parameter.valueType === 'secure-hash') {
108
+ continue;
109
+ }
110
+ const value = deriveValue(parameter, flow, input, profile, now, generated);
111
+ if (value !== undefined) {
112
+ parameters[parameter.name] = value;
113
+ }
114
+ }
115
+ // Extras naming an undeclared field are kept rather than dropped, so the
116
+ // unknown-fields rule can tell the caller the field does not belong.
117
+ for (const [name, value] of Object.entries(input.extras ?? {})) {
118
+ parameters[name] ??= value;
119
+ }
120
+ const validation = validatePayload(flow, parameters, {
121
+ registeredReturnUrl: profile.returnUrl,
122
+ now,
123
+ });
124
+ if (!validation.valid) {
125
+ return {
126
+ flowId: flow.id,
127
+ parameters,
128
+ secureHash: '',
129
+ hashBreakdown: buildHashString(parameters, integritySalt, requestHashOptions(flow)),
130
+ validation,
131
+ generated,
132
+ };
133
+ }
134
+ const hashBreakdown = buildHashString(parameters, integritySalt, requestHashOptions(flow));
135
+ const secureHash = computeSecureHash(parameters, integritySalt, requestHashOptions(flow));
136
+ // Read from the flow rather than spelled `pp_SecureHash` here. That is
137
+ // JazzCash's name for the field, and a payload built for a provider that names
138
+ // its own would carry a correct digest in a field the gateway never reads,
139
+ // while the field it does read is absent. A flow that declares no signature
140
+ // field gets no signature key, rather than one under a borrowed name.
141
+ const signatureField = signatureFieldName(flow);
142
+ return {
143
+ flowId: flow.id,
144
+ parameters: signatureField === undefined ? parameters : { ...parameters, [signatureField]: secureHash },
145
+ secureHash,
146
+ hashBreakdown,
147
+ validation,
148
+ generated,
149
+ };
150
+ }
151
+ /** Throwing variant, for callers that cannot proceed with an invalid payload. */
152
+ export function buildTransactionOrThrow(flow, input, profile, integritySalt = profile.integritySalt) {
153
+ const built = buildTransaction(flow, input, profile, integritySalt);
154
+ if (!built.validation.valid) {
155
+ throw new JazzCashValidationError(`Cannot build a ${flow.id} payload: ${built.validation.errors.map((entry) => entry.message).join(' ')}`, { details: { flowId: flow.id, errors: built.validation.errors } });
156
+ }
157
+ return built;
158
+ }
159
+ //# sourceMappingURL=transaction-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-builder.js","sourceRoot":"","sources":["../../src/builder/transaction-builder.ts"],"names":[],"mappings":"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"}