@fangorn-network/westmarch 0.0.19-dev → 2026.10.2-0.0-dev

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 (590) hide show
  1. package/README.md +33 -3
  2. package/docs/app-to-agent.md +100 -27
  3. package/package.json +9 -5
  4. package/plugin/scripts/fx.mjs +7 -9
  5. package/site/dist/assets/AccountNotFoundScreen-C4njXc69-RUyAWRzV.js +1 -0
  6. package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-ZV-LlYBe.js +31 -0
  7. package/site/dist/assets/Address-H8kD1d9O-CGQnt7Pu.js +17 -0
  8. package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-CKn2JLwq.js +6 -0
  9. package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-9oIP9fma.js +1 -0
  10. package/site/dist/assets/ArrowsRightLeftIcon-BEhBD_6N.js +1 -0
  11. package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-D1wLlSJs.js +1 -0
  12. package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-CSBbHTyz.js +1 -0
  13. package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-BsRq-xBt.js +1 -0
  14. package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-BPdhsKvN.js +103 -0
  15. package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-CEGNdrkr.js +1 -0
  16. package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-Da9P7eSx.js +68 -0
  17. package/site/dist/assets/CaptchaScreen-DbpvkIGx-BecgMnD_.js +1 -0
  18. package/site/dist/assets/CheckCircleIcon-DBiWFjO6.js +1 -0
  19. package/site/dist/assets/CheckCircleIcon-DzG2ROJZ.js +1 -0
  20. package/site/dist/assets/Checkbox-D1EDeo41-DMHcj9o_.js +52 -0
  21. package/site/dist/assets/ChevronDownIcon-2Os56gUt.js +1 -0
  22. package/site/dist/assets/Chip-CZKIKt9K-BWzs9fj5.js +26 -0
  23. package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-CFvcSiDs.js +16 -0
  24. package/site/dist/assets/ConnectEmailForm-B-VRE0MN-BozkCg8q.js +3 -0
  25. package/site/dist/assets/ConnectLedgerScreen-DWHABGot-DaCnbBzh.js +10 -0
  26. package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-DUkCLkxD.js +1 -0
  27. package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-Dv_5nMkZ.js +1 -0
  28. package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-DSGEeB3Y.js +1 -0
  29. package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-C-s4s_Lq.js +95 -0
  30. package/site/dist/assets/ConnectWalletView-DqI-PTvX-BKX7fdYr.js +74 -0
  31. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-DSoAuMFZ.js +7 -0
  32. package/site/dist/assets/CopyToClipboard-i_OQSBJr-CZTXyfV0.js +39 -0
  33. package/site/dist/assets/CopyableText-CQapvaMr-DHO818I0.js +28 -0
  34. package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-DW4nRGfz.js +1 -0
  35. package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-DH8Nnb4Y.js +22 -0
  36. package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-gfUS_uV5.js +1 -0
  37. package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-DZj9HTHc.js +1 -0
  38. package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-eHYsDK9W.js +187 -0
  39. package/site/dist/assets/DepositAddressScreen-DBLRs7aI-DK_XVgVk.js +8 -0
  40. package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-6gRZzhLe.js +1 -0
  41. package/site/dist/assets/{EmailInputForm-Cqo1mda8-B2NG3K5V.js → EmailInputForm-Cqo1mda8-CZD4r5LM.js} +11 -11
  42. package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-BZu2ae0k.js +1 -0
  43. package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-86pviemJ.js +1 -0
  44. package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-vDcvT53Y.js +23 -0
  45. package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-rNJAtSJc.js +1 -0
  46. package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-I8Q95280.js +1 -0
  47. package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-Coi7OxoI.js +1 -0
  48. package/site/dist/assets/EnrollTotp-Dibew4dp-DC7FrDgo.js +66 -0
  49. package/site/dist/assets/EnvelopeIcon-DY6ERnW7.js +1 -0
  50. package/site/dist/assets/ErrorBanner-BcpGRt0h-BvESwN99.js +21 -0
  51. package/site/dist/assets/{ErrorMessage-D8VaAP5m-CrZOnUyg.js → ErrorMessage-D8VaAP5m-oSruKN8L.js} +2 -2
  52. package/site/dist/assets/ErrorScreen-DipdTWzE-DnKGxH1Z.js +4 -0
  53. package/site/dist/assets/ExclamationCircleIcon-BZhlqH0r.js +1 -0
  54. package/site/dist/assets/ExclamationTriangleIcon-CkAOJIYV.js +1 -0
  55. package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-4pi7jooW.js +75 -0
  56. package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-z2XCMaLL.js +28 -0
  57. package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-CBVA9v1-.js +491 -0
  58. package/site/dist/assets/FingerPrintIcon-ra2dqmJO.js +1 -0
  59. package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-DwAwc6Ny.js +1 -0
  60. package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-CZszQsZf.js +1 -0
  61. package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-DfX6nvFQ.js +58 -0
  62. package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-CDS_sk_t.js +1 -0
  63. package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-CPfNQemT.js +1 -0
  64. package/site/dist/assets/GlobeAltIcon-SEUEIe_E.js +1 -0
  65. package/site/dist/assets/GooglePay-B53WnudL-aap7zwag.js +1 -0
  66. package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-DgSjCjQI.js +4 -0
  67. package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-DO4wICml.js +1 -0
  68. package/site/dist/assets/InfoBanner-Cb3p1z12-CDWt2ADo.js +22 -0
  69. package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-Ba19XoBr.js +1 -0
  70. package/site/dist/assets/InstallWalletScreen-DTA8dwLv-DGpewEch.js +1 -0
  71. package/site/dist/assets/{JsonTree-BHzNC-ic-DcNcbSoM.js → JsonTree-BHzNC-ic-pAEq1bl9.js} +3 -3
  72. package/site/dist/assets/{LabelXs-oqZNqbm_-iafrj25N.js → LabelXs-oqZNqbm_-D09YjVR4.js} +2 -2
  73. package/site/dist/assets/LandingScreen-CGWUoSUG-CUOCWUXd.js +1 -0
  74. package/site/dist/assets/{Layouts-BMRfo5hw-CeCOyCLK.js → Layouts-BMRfo5hw-D2u1-w8g.js} +16 -16
  75. package/site/dist/assets/Link-BdDilT2T-BYiP1zvW.js +40 -0
  76. package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-Tb6cAepT.js +77 -0
  77. package/site/dist/assets/LinkEmailScreen-dKo9frwc-pq0NF2JO.js +1 -0
  78. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-D9MOmDqg.js +117 -0
  79. package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-B80UJqAZ.js +1 -0
  80. package/site/dist/assets/{LoadingSkeleton-BMsgO5PV-CiEyS5PZ.js → LoadingSkeleton-BMsgO5PV-BRMh4Fv4.js} +6 -6
  81. package/site/dist/assets/LockClosedIcon-BqkoEL9J.js +1 -0
  82. package/site/dist/assets/LoginFailedScreen-CN0dJV6U-DlnOM-Kh.js +1 -0
  83. package/site/dist/assets/ManualTransferScreen-CHqcuqbs-DSShupq9.js +1 -0
  84. package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-DUPV_SLA.js +1 -0
  85. package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-D96GpzXX.js +1 -0
  86. package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-CYQDa4ND.js +1 -0
  87. package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-CJtSAXGN.js +1 -0
  88. package/site/dist/assets/ModalFooter-BCuEK_nz-D2I8KWtk.js +403 -0
  89. package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-Bx5aHy-z.js +16 -0
  90. package/site/dist/assets/OAuthStatusScreen-ufbOa-da-CS6988X2.js +1 -0
  91. package/site/dist/assets/OpenLink-CUpJ1mOr-EZWVSX2r.js +39 -0
  92. package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-BY4eK5Jh.js +1 -0
  93. package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-LXys76u9.js +6 -0
  94. package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-RczvLvmo.js +20 -0
  95. package/site/dist/assets/{PhArrowCircleDown-D97G-BOA.js → PhArrowCircleDown-BtlNV0TZ.js} +5 -5
  96. package/site/dist/assets/PhArrowClockwise-mOiWYLMV.js +14 -0
  97. package/site/dist/assets/PhArrowDown-CkoOD89h.js +14 -0
  98. package/site/dist/assets/PhArrowLeft-C0jlxVhM.js +14 -0
  99. package/site/dist/assets/PhArrowRight-BI-V03Xf.js +14 -0
  100. package/site/dist/assets/{PhArrowSquareOut-Bk2CMG3I.js → PhArrowSquareOut-DnQ7n_B4.js} +5 -5
  101. package/site/dist/assets/PhArrowUp-izKvURUW.js +14 -0
  102. package/site/dist/assets/PhArrowUpRight-Bn-JhHsY.js +14 -0
  103. package/site/dist/assets/{PhArrowsClockwise-BXRn1GEl.js → PhArrowsClockwise-Brtx2Re-.js} +5 -5
  104. package/site/dist/assets/{PhArrowsDownUp-DM09Jo_3.js → PhArrowsDownUp-PZosTqZG.js} +5 -5
  105. package/site/dist/assets/PhArrowsLeftRight-CYsRQ2qh.js +14 -0
  106. package/site/dist/assets/{PhBank-fHbgCqqZ.js → PhBank-hhPAIPVb.js} +5 -5
  107. package/site/dist/assets/PhBrowser-BjzAmrHO.js +14 -0
  108. package/site/dist/assets/PhCaretDown-ddSjwcwm.js +14 -0
  109. package/site/dist/assets/PhCaretLeft-B7YLoNEF.js +14 -0
  110. package/site/dist/assets/PhCaretRight-BY8D5MIg.js +14 -0
  111. package/site/dist/assets/PhCaretUp-BG10nSut.js +14 -0
  112. package/site/dist/assets/PhCheck-DrKd7pBC.js +14 -0
  113. package/site/dist/assets/{PhCircleHalf-MJZeRBGF.js → PhCircleHalf-Bk9C4DvT.js} +5 -5
  114. package/site/dist/assets/PhClock-Sj17weCB.js +14 -0
  115. package/site/dist/assets/{PhCompass-hYn3HhGN.js → PhCompass-Df1ugFO-.js} +5 -5
  116. package/site/dist/assets/PhCopy-rgttky8E.js +14 -0
  117. package/site/dist/assets/{PhCreditCard-Fy4pzwtt.js → PhCreditCard-CZpdid2n.js} +5 -5
  118. package/site/dist/assets/{PhCurrencyDollar-BgiaenCi.js → PhCurrencyDollar-B6IKKjue.js} +5 -5
  119. package/site/dist/assets/{PhDesktop-CxrzCSv5.js → PhDesktop-BuCDXYJj.js} +5 -5
  120. package/site/dist/assets/PhDeviceMobile-CnybhXY-.js +14 -0
  121. package/site/dist/assets/PhDotsThree-CSAEcba1.js +14 -0
  122. package/site/dist/assets/PhEnvelope-SmaNeXoQ.js +14 -0
  123. package/site/dist/assets/PhFunnelSimple-DKx35ITq.js +14 -0
  124. package/site/dist/assets/{PhGlobe-DvmSc9_A.js → PhGlobe-q1mqj65V.js} +5 -5
  125. package/site/dist/assets/{PhIdentificationCard-CfkZm-5K.js → PhIdentificationCard-BeLXJpfZ.js} +5 -5
  126. package/site/dist/assets/{PhImage-Cf0J2ZfJ.js → PhImage-BYrKfN9k.js} +5 -5
  127. package/site/dist/assets/{PhInfo-Bwi51-2X.js → PhInfo-X33f06Ej.js} +5 -5
  128. package/site/dist/assets/{PhLightbulb-C4FZV7Es.js → PhLightbulb-DMZJsowR.js} +5 -5
  129. package/site/dist/assets/PhMagnifyingGlass-B6D0sWFL.js +14 -0
  130. package/site/dist/assets/{PhPaperPlaneRight-zxQVvPLX.js → PhPaperPlaneRight-Dvo-nXr9.js} +5 -5
  131. package/site/dist/assets/PhPlus-CBvZvLax.js +14 -0
  132. package/site/dist/assets/{PhPower-CFyWDmgD.js → PhPower-D8-AcNM6.js} +5 -5
  133. package/site/dist/assets/{PhPuzzlePiece-BjoNVfST.js → PhPuzzlePiece-C-7mYqGO.js} +5 -5
  134. package/site/dist/assets/{PhQrCode-CP3tFauY.js → PhQrCode-uIXlI5ER.js} +5 -5
  135. package/site/dist/assets/{PhQuestion-wOWJBd3G.js → PhQuestion-rUoqC2sC.js} +5 -5
  136. package/site/dist/assets/{PhQuestionMark-CV0k9C0Y.js → PhQuestionMark-W55Txvvb.js} +5 -5
  137. package/site/dist/assets/{PhSealCheck-vIKzREuN.js → PhSealCheck-BeVLq9PH.js} +5 -5
  138. package/site/dist/assets/{PhSignOut-CxELV-i0.js → PhSignOut-Cq2PivQ6.js} +5 -5
  139. package/site/dist/assets/{PhSpinner-CGDmbzUd.js → PhSpinner-CZMtAFdX.js} +5 -5
  140. package/site/dist/assets/{PhTrash-C9PD0SAt.js → PhTrash-BamrmMsN.js} +5 -5
  141. package/site/dist/assets/{PhUser-0sWNXQeZ.js → PhUser-A2fxqIV0.js} +5 -5
  142. package/site/dist/assets/{PhVault-6JTskUcC.js → PhVault-B8m1usHw.js} +5 -5
  143. package/site/dist/assets/{PhWarning-CoKs3gz6.js → PhWarning-CpkID9oi.js} +5 -5
  144. package/site/dist/assets/PhWarningCircle-Cm58gXb9.js +14 -0
  145. package/site/dist/assets/PhX-C3b4cCEy.js +14 -0
  146. package/site/dist/assets/PhoneIcon-CzbssTb8.js +1 -0
  147. package/site/dist/assets/PinInput-DbZ0b1i1-1DtLWL81.js +247 -0
  148. package/site/dist/assets/QrCode-DbnZwlkH-ChwcUk_h.js +22 -0
  149. package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-C79jd345.js +1 -0
  150. package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-C9c0x-yq.js +1 -0
  151. package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-PNqHb6CI.js +7 -0
  152. package/site/dist/assets/{Screen-D30meWsY-CCeVNuWs.js → Screen-D30meWsY-DDum2qlY.js} +22 -22
  153. package/site/dist/assets/{ScreenHeader-CHmc4-Lu-DjyrH7IK.js → ScreenHeader-CHmc4-Lu-BqrAEXbV.js} +4 -4
  154. package/site/dist/assets/ScreenLayout-OwaQQcxH-B4Z8FjFp.js +1 -0
  155. package/site/dist/assets/{SelectSourceAsset-CWFog6gm-RKjBsB6m.js → SelectSourceAsset-CWFog6gm-8iXuqbAs.js} +18 -18
  156. package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-CUpQZ9wq.js +14 -0
  157. package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-ZzvPLj2s.js +15 -0
  158. package/site/dist/assets/ShieldCheckIcon-Bjwe_-PV.js +1 -0
  159. package/site/dist/assets/SignRequestScreen-BHKv32KR-0qGeNipB.js +26 -0
  160. package/site/dist/assets/{StackedContainer-B2vaEl56-eQCM2cmv.js → StackedContainer-B2vaEl56-C-ojzCoQ.js} +2 -2
  161. package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-C3lgJb68.js +20 -0
  162. package/site/dist/assets/{Subtitle-CV-2yKE4-zxWw2m1Q.js → Subtitle-CV-2yKE4-o-1FQLlX.js} +2 -2
  163. package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-l35_C2DG.js +1 -0
  164. package/site/dist/assets/{Title-BnzYV3Is-B_JpTatT.js → Title-BnzYV3Is-RX1f0RV-.js} +2 -2
  165. package/site/dist/assets/TodoList-DnyULl18-JxWWU9KA.js +36 -0
  166. package/site/dist/assets/TransactionDetails-e9nesl30-C91nJPM9.js +109 -0
  167. package/site/dist/assets/TransactionErrorView-BDBNqA_f-Cpm-4xzm.js +178 -0
  168. package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-BWCH7-Si.js +31 -0
  169. package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-BWMeJabk.js +6 -0
  170. package/site/dist/assets/TurnstileWrapper-B7sNddys-Dgr80Gih.js +1 -0
  171. package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-Clk4zk-8.js +1 -0
  172. package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-BgRsoR3B.js +1 -0
  173. package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-D-SU-vAz.js +1 -0
  174. package/site/dist/assets/{Value-DTgR824E-BRuIGiec.js → Value-DTgR824E-DZpvBCWi.js} +7 -7
  175. package/site/dist/assets/WalletCards-DH1rqayz-UuZ4i_Ze.js +1 -0
  176. package/site/dist/assets/WalletIcon-B1i03Vqc.js +1 -0
  177. package/site/dist/assets/WalletInfoCard-sq_2wgFg-TXTxmb8L.js +29 -0
  178. package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-CbrFb0ON.js +1 -0
  179. package/site/dist/assets/WalletLink-DK5LB5Ha-BYQZV7UV.js +20 -0
  180. package/site/dist/assets/WalletOverflowButton-bfCnp-9T-CNgSPnTS.js +1 -0
  181. package/site/dist/assets/WarningBanner-ZZqCEtZK-DNZUUOph.js +21 -0
  182. package/site/dist/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  183. package/site/dist/assets/analytics-mkkvFRju-DOXuftJB.js +1 -0
  184. package/site/dist/assets/basic-C9wn6QoQ.js +1575 -0
  185. package/site/dist/assets/bytes-CjWw8TJh.js +1 -0
  186. package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-tV1Idewc.js +1 -0
  187. package/site/dist/assets/ccip-BhHEqVIW.js +1 -0
  188. package/site/dist/assets/check-C_DTyjLS.js +1 -0
  189. package/site/dist/assets/chevron-down-iklXXH-z.js +1 -0
  190. package/site/dist/assets/circle-alert-KEOUF48T.js +1 -0
  191. package/site/dist/assets/circle-check-big-BJ_ADwB4.js +1 -0
  192. package/site/dist/assets/circle-x-BSfWmhYk.js +1 -0
  193. package/site/dist/assets/client-BnDcP42J.js +9 -0
  194. package/site/dist/assets/client-DH86IrJA.js +125 -0
  195. package/site/dist/assets/coinbase-DCPC2L_R-2ivYfoMv.js +3 -0
  196. package/site/dist/assets/copy-sK00DOfH.js +1 -0
  197. package/site/dist/assets/core-CRE213RM.js +211 -0
  198. package/site/dist/assets/createLucideIcon-D9OK_uxG.js +1 -0
  199. package/site/dist/assets/custom-V1wex-Di.js +1 -0
  200. package/site/dist/assets/dijkstra-COg3n3zL.js +1 -0
  201. package/site/dist/assets/embed.worker-BRIYO7m8.js +1 -0
  202. package/site/dist/assets/encodePacked-DyXYq3Cc.js +1 -0
  203. package/site/dist/assets/ethers-zTjbodk5-DSYOi6tU.js +1 -0
  204. package/site/dist/assets/external-link-Cdp8NBio.js +1 -0
  205. package/site/dist/assets/fallback-DiFue5Zm.js +1 -0
  206. package/site/dist/assets/farcaster-DPlSjvF5-DP2DLoHZ.js +1 -0
  207. package/site/dist/assets/features-B6BTj_BL.js +5 -0
  208. package/site/dist/assets/fingerprint-pattern-gFJTz5e4.js +1 -0
  209. package/site/dist/assets/floating-ui.react-D9ndYqYK.js +1 -0
  210. package/site/dist/assets/floating-ui.react-dom-CNbOgOFt.js +1 -0
  211. package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-CkAr4Oc0.js +1 -0
  212. package/site/dist/assets/getChainName-DjpPdUSc-c2urPd0g.js +1 -0
  213. package/site/dist/assets/getErc20Balance-jXNpFf0N-mFQ9Iqk-.js +1 -0
  214. package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-Dx5he_uG.js +1 -0
  215. package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-C446pzMl.js +1 -0
  216. package/site/dist/assets/getTransactionCount-80UHlwAV.js +1 -0
  217. package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-FDalV59C.js +1 -0
  218. package/site/dist/assets/hashTypedData-Beq57Ogb.js +22 -0
  219. package/site/dist/assets/hooks.module-ClpaQ1Tg.js +1 -0
  220. package/site/dist/assets/hourglass-CB7z_I9H.js +1 -0
  221. package/site/dist/assets/http-BocEfKYb.js +19 -0
  222. package/site/dist/assets/index-0knDOgU9.js +1 -0
  223. package/site/dist/assets/index-9jNeS_nC.js +1 -0
  224. package/site/dist/assets/index-B--T-Fmt.js +16 -0
  225. package/site/dist/assets/index-BDkarAkX.js +2 -0
  226. package/site/dist/assets/index-BMfMy017.js +679 -0
  227. package/site/dist/assets/index-BOd8jv8-.js +1 -0
  228. package/site/dist/assets/index-BdEw5wyl-2VGMzHIs.js +1 -0
  229. package/site/dist/assets/index-C8ThRelw.js +9 -0
  230. package/site/dist/assets/{index-CWARkn2w-Cezl_uBr.js → index-CWARkn2w-D6ikWJWj.js} +7 -7
  231. package/site/dist/assets/{wui-ux-by-reown-fVu0QkI4.js → index-CztIxJB6.js} +296 -296
  232. package/site/dist/assets/index-D4LdLFDC.js +1 -0
  233. package/site/dist/assets/index-D6T-s6sR.js +1 -0
  234. package/site/dist/assets/index-D7396TWe.js +1 -0
  235. package/site/dist/assets/index-DdxtHe81.js +2 -0
  236. package/site/dist/assets/index-DvMddJcd-D7AEQrzj.js +12 -0
  237. package/site/dist/assets/index-nibyPLVP.js +1 -0
  238. package/site/dist/assets/index.browser-B6Bt5URJ.js +1 -0
  239. package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-D7xtzRqA.js +1 -0
  240. package/site/dist/assets/landmark-CMLKifhk.js +1 -0
  241. package/site/dist/assets/lock-BkyjNE8h.js +1 -0
  242. package/site/dist/assets/mail-B6-Tq9Ld.js +1 -0
  243. package/site/dist/assets/native-CJ5et6AR.js +1 -0
  244. package/site/dist/assets/nonceManager-zkW7cM66.js +1 -0
  245. package/site/dist/assets/parseEther-C7aOvuze.js +1 -0
  246. package/site/dist/assets/parseSignature-BIjcuWdB.js +1 -0
  247. package/site/dist/assets/preload-helper-PPVm8Dsz.js +1 -0
  248. package/site/dist/assets/privateKeyToAccount-CRvvpHWf.js +1 -0
  249. package/site/dist/assets/property-CnFDNXw5.js +3 -0
  250. package/site/dist/assets/react-auth_false-DedQs79w.js +1 -0
  251. package/site/dist/assets/reservoir-x-nGuZkT-DFxAFt2v.js +1 -0
  252. package/site/dist/assets/roles-DV_6FRBZ.js +1 -0
  253. package/site/dist/assets/safe-url-D7SRPu33-A8zMgOTd.js +1 -0
  254. package/site/dist/assets/serializeErc6492Signature-CeJeL3h6.js +1 -0
  255. package/site/dist/assets/serializeTransaction-L-_Ej-jW.js +8 -0
  256. package/site/dist/assets/{shared-DRZUmnL5-xqAUARWo.js → shared-DRZUmnL5-MWD-C-pp.js} +33 -33
  257. package/site/dist/assets/{shared-FM0rljBt--Avg6q2R.js → shared-FM0rljBt-c4eSjzGj.js} +6 -6
  258. package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-CF2QteTJ.js +1 -0
  259. package/site/dist/assets/simulateTransaction-CfuOrae4-BHUMPf6Q.js +1 -0
  260. package/site/dist/assets/smartphone-DAN5rY0T.js +1 -0
  261. package/site/dist/assets/stripe.esm-Dv8C3q95.js +2 -0
  262. package/site/dist/assets/styles-BsotlekN-Cjuu2SDV.js +9 -0
  263. package/site/dist/assets/{styles-Cm9H63WO-D90SsXOs.js → styles-Cm9H63WO-Cv1TbqYi.js} +17 -17
  264. package/site/dist/assets/{styles-DVyDvTdj-BTABn2K8.js → styles-DVyDvTdj-CI4xZNHp.js} +8 -8
  265. package/site/dist/assets/{styles-hslXy6xG-D-49b1rk.js → styles-hslXy6xG-DeVcFoDD.js} +23 -23
  266. package/site/dist/assets/telegram-B-JqnkqZ-DTjJLkIF.js +1 -0
  267. package/site/dist/assets/to-ui-error-DWe-qwS3-Dx3yzcV0.js +4 -0
  268. package/site/dist/assets/toAccount-Bq6rbpbI.js +1 -0
  269. package/site/dist/assets/transaction-BNTP-bFm-CrebgH-D.js +1 -0
  270. package/site/dist/assets/transactionReceipt-BwJl-gjg.js +1 -0
  271. package/site/dist/assets/transfer-6YztDh-t-DU6hH7CZ.js +1 -0
  272. package/site/dist/assets/transformers.web-BEKVh7pD.js +40 -0
  273. package/site/dist/assets/transformers.web-aWa49tv1.js +40 -0
  274. package/site/dist/assets/triangle-alert-ndoiBs4y.js +1 -0
  275. package/site/dist/assets/twitch-5IOe4sIQ-BXviIywg.js +1 -0
  276. package/site/dist/assets/useGetSolPrice-x7gfUIHJ-C7axYJ--.js +1 -0
  277. package/site/dist/assets/useGetTokenPrice-CaoUkb79-CR4CrguU.js +1 -0
  278. package/site/dist/assets/useI18n-C-5n_noF-C_t8QqBJ.js +1 -0
  279. package/site/dist/assets/useWalletBalance-CZnP5f_f-BnSHLVI_.js +1 -0
  280. package/site/dist/assets/w3m-modal-Bz5KWTQ-.js +1174 -0
  281. package/site/dist/assets/wallet-DTM31trz.js +2 -0
  282. package/site/dist/assets/wallet-UESEqPei.js +1 -0
  283. package/site/dist/assets/wallet-connect-BvJtUsDt-CnvUnFbz.js +1 -0
  284. package/site/dist/assets/walletconnect-v2-3frQFwbg-CzQk99gS.js +15 -0
  285. package/site/dist/assets/x-B2_XdOVQ.js +1 -0
  286. package/site/dist/index.html +120 -8
  287. package/site/feed.js +16 -1
  288. package/site/no-model.js +4 -0
  289. package/site/worker.js +597 -58
  290. package/src/agent/agent-card.js +20 -11
  291. package/src/agent/mcp.js +150 -316
  292. package/src/agent/view-tools.js +53 -12
  293. package/src/agent/x402.js +379 -44
  294. package/src/core/embed.js +51 -52
  295. package/src/core/embed.worker.js +1 -1
  296. package/src/core/shard.js +7 -3
  297. package/src/discover/apps.js +4 -3
  298. package/src/discover/explore.js +36 -22
  299. package/src/market/reactions.js +2 -2
  300. package/src/publish/devnet.js +95 -0
  301. package/src/publish/lint.js +2 -1
  302. package/src/publish/ship.js +517 -236
  303. package/src/publish/view-cli.js +11 -10
  304. package/src/publish/view.js +359 -206
  305. package/src/taste/taste-doc.js +3 -2
  306. package/src/taste/taste.js +2 -2
  307. package/src/taste/vault.js +3 -1
  308. package/site/dist/assets/AccountNotFoundScreen-C4njXc69-BOfmiSH1.js +0 -1
  309. package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-B6uvYyqa.js +0 -31
  310. package/site/dist/assets/Address-H8kD1d9O-DcHv7A8C.js +0 -17
  311. package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-v2wz-N-s.js +0 -6
  312. package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-DhVy9iGN.js +0 -1
  313. package/site/dist/assets/ApiController-BbhXeqTV.js +0 -5
  314. package/site/dist/assets/ArrowsRightLeftIcon-cp60yobq.js +0 -1
  315. package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-B0eT1zE6.js +0 -1
  316. package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-DL5PH-v_.js +0 -1
  317. package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-n1BsRPqc.js +0 -1
  318. package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-BVl2BJDY.js +0 -103
  319. package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-BD-OZUQb.js +0 -1
  320. package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-CaYrzRje.js +0 -68
  321. package/site/dist/assets/CaptchaScreen-DbpvkIGx-BQJ7inx1.js +0 -1
  322. package/site/dist/assets/CheckCircleIcon-BM409mGI.js +0 -1
  323. package/site/dist/assets/CheckCircleIcon-NCOQc0Gs.js +0 -1
  324. package/site/dist/assets/Checkbox-D1EDeo41-rHlvsZzP.js +0 -52
  325. package/site/dist/assets/ChevronDownIcon-CW-4MSpE.js +0 -1
  326. package/site/dist/assets/Chip-CZKIKt9K-CutJG010.js +0 -26
  327. package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-DDaMC7cl.js +0 -16
  328. package/site/dist/assets/ConnectEmailForm-B-VRE0MN-DVSf4tFJ.js +0 -3
  329. package/site/dist/assets/ConnectLedgerScreen-DWHABGot-h0uYIUi6.js +0 -10
  330. package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-DP19hJq5.js +0 -1
  331. package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-DHvijlTx.js +0 -1
  332. package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-ewmXYPTQ.js +0 -1
  333. package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-DUYdmVtr.js +0 -95
  334. package/site/dist/assets/ConnectWalletView-DqI-PTvX-RobGErVW.js +0 -74
  335. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-Bbiq3hY6.js +0 -1
  336. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-DPkOGNWl.js +0 -7
  337. package/site/dist/assets/ConnectorUtil-BO1L6VvV.js +0 -21
  338. package/site/dist/assets/ConstantsUtil-DmLsRHAl.js +0 -198
  339. package/site/dist/assets/CopyToClipboard-i_OQSBJr-DujUHNzW.js +0 -39
  340. package/site/dist/assets/CopyableText-CQapvaMr-DMIdpDaU.js +0 -28
  341. package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-DbGy4QyA.js +0 -1
  342. package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-B3WqJZBh.js +0 -22
  343. package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-CmUDoS0C.js +0 -1
  344. package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-fcO51q5H.js +0 -1
  345. package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-ClAb_j1B.js +0 -187
  346. package/site/dist/assets/DepositAddressScreen-DBLRs7aI-CN1P_KY9.js +0 -8
  347. package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-BtDZmuEN.js +0 -1
  348. package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-D3pExuaW.js +0 -1
  349. package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-CLsJbPYQ.js +0 -1
  350. package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-DI6bu-oi.js +0 -23
  351. package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-BQ9Ygr0P.js +0 -1
  352. package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-CxrfLr5q.js +0 -1
  353. package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-DHZRGoTN.js +0 -1
  354. package/site/dist/assets/EnrollTotp-Dibew4dp-7gVtJ1Jt.js +0 -66
  355. package/site/dist/assets/EnvelopeIcon-Dh2vSVj4.js +0 -1
  356. package/site/dist/assets/ErrorBanner-BcpGRt0h-BKOYTyCi.js +0 -21
  357. package/site/dist/assets/ErrorScreen-DipdTWzE-BT8TtRTx.js +0 -4
  358. package/site/dist/assets/ErrorScreen-DipdTWzE-DAam41Xl.js +0 -1
  359. package/site/dist/assets/ExclamationCircleIcon-DUA2wMfO.js +0 -1
  360. package/site/dist/assets/ExclamationTriangleIcon-eZfaqcFq.js +0 -1
  361. package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-BPCBi37Q.js +0 -75
  362. package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-XCmWpnUd.js +0 -28
  363. package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-DJRcUh2N.js +0 -491
  364. package/site/dist/assets/FingerPrintIcon-Dm6kxmg7.js +0 -1
  365. package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-BfNVSTb1.js +0 -1
  366. package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-BQdbJ5Bb.js +0 -1
  367. package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-BfvMcHb6.js +0 -58
  368. package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-VBfbahnA.js +0 -1
  369. package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-CMuBYf64.js +0 -1
  370. package/site/dist/assets/GlobeAltIcon-vqrVV5ho.js +0 -1
  371. package/site/dist/assets/GooglePay-B53WnudL-BX5_WtCx.js +0 -1
  372. package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-D-I8j7NO.js +0 -4
  373. package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-BY3j50El.js +0 -1
  374. package/site/dist/assets/InfoBanner-Cb3p1z12-DLBl_Ywy.js +0 -22
  375. package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-DLSV_NjP.js +0 -1
  376. package/site/dist/assets/InstallWalletScreen-DTA8dwLv-CxreyXoD.js +0 -1
  377. package/site/dist/assets/LandingScreen-CGWUoSUG-Q7hgXKvM.js +0 -1
  378. package/site/dist/assets/Link-BdDilT2T-BEDEdHuS.js +0 -40
  379. package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-DK1z_v7y.js +0 -77
  380. package/site/dist/assets/LinkEmailScreen-dKo9frwc-BYYpJ5-6.js +0 -1
  381. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-uhub9C26.js +0 -1
  382. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-uid22VTN.js +0 -117
  383. package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-CVQibNi9.js +0 -1
  384. package/site/dist/assets/Loader-UAZqxsnw-Cy7hEE2f.js +0 -62
  385. package/site/dist/assets/LockClosedIcon-BgY_5v_Z.js +0 -1
  386. package/site/dist/assets/LoginFailedScreen-CN0dJV6U-DhUMiJZJ.js +0 -1
  387. package/site/dist/assets/ManualTransferScreen-CHqcuqbs-DMygAXMU.js +0 -1
  388. package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-_1GFUSIg.js +0 -1
  389. package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-DLnBJ5b8.js +0 -1
  390. package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-BUJY1lzs.js +0 -1
  391. package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-25l5fVun.js +0 -1
  392. package/site/dist/assets/ModalFooter-BCuEK_nz-c-khvG4Y.js +0 -403
  393. package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-BRFN2eXr.js +0 -16
  394. package/site/dist/assets/OAuthStatusScreen-ufbOa-da-DL30vu07.js +0 -1
  395. package/site/dist/assets/OpenLink-CUpJ1mOr-DfAvJRyK.js +0 -39
  396. package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-DtxhRQyw.js +0 -1
  397. package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-CNfu8ujT.js +0 -6
  398. package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-BR6z6xE8.js +0 -20
  399. package/site/dist/assets/PhArrowClockwise-DVgyFuez.js +0 -14
  400. package/site/dist/assets/PhArrowDown-87b1BizM.js +0 -14
  401. package/site/dist/assets/PhArrowLeft-Da0MfnbK.js +0 -14
  402. package/site/dist/assets/PhArrowRight-AdrIL4DW.js +0 -14
  403. package/site/dist/assets/PhArrowUp-4sgyKPGx.js +0 -14
  404. package/site/dist/assets/PhArrowUpRight-BNghD2zq.js +0 -14
  405. package/site/dist/assets/PhArrowsLeftRight-MuKBLUoF.js +0 -14
  406. package/site/dist/assets/PhBrowser-2-9m-AkM.js +0 -14
  407. package/site/dist/assets/PhCaretDown-BDNabFuL.js +0 -14
  408. package/site/dist/assets/PhCaretLeft-CI460R-A.js +0 -14
  409. package/site/dist/assets/PhCaretRight-D7ZS3Ls8.js +0 -14
  410. package/site/dist/assets/PhCaretUp-C-iIfyvO.js +0 -14
  411. package/site/dist/assets/PhCheck-DxQXn57r.js +0 -14
  412. package/site/dist/assets/PhClock-x3MS3Mwi.js +0 -14
  413. package/site/dist/assets/PhCopy-CWNYcABI.js +0 -14
  414. package/site/dist/assets/PhDeviceMobile-CsyA5Goi.js +0 -14
  415. package/site/dist/assets/PhDotsThree-D-k1BiYg.js +0 -14
  416. package/site/dist/assets/PhEnvelope-D8kzeNox.js +0 -14
  417. package/site/dist/assets/PhFunnelSimple-CfQs5DAW.js +0 -14
  418. package/site/dist/assets/PhMagnifyingGlass-C9u8jSCJ.js +0 -14
  419. package/site/dist/assets/PhPlus-C4UoW-2n.js +0 -14
  420. package/site/dist/assets/PhWarningCircle-BXHw1fCt.js +0 -14
  421. package/site/dist/assets/PhX-DX0SFIqC.js +0 -14
  422. package/site/dist/assets/PhoneIcon-CvIiPwYQ.js +0 -1
  423. package/site/dist/assets/PinInput-DbZ0b1i1-CDXZBdQx.js +0 -247
  424. package/site/dist/assets/PrivyPluginContext-DA-yS5vO-CtQWBiV2.js +0 -1
  425. package/site/dist/assets/QrCode-DbnZwlkH-BymHrKY7.js +0 -22
  426. package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-Dro1btv5.js +0 -1
  427. package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-C1q1hiaN.js +0 -1
  428. package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-C21D20gD.js +0 -7
  429. package/site/dist/assets/SIWXUtil-CHZVugix.js +0 -1
  430. package/site/dist/assets/ScreenLayout-OwaQQcxH-CrQM6kvA.js +0 -1
  431. package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-BcWHJoEG.js +0 -14
  432. package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-kq1zvA7d.js +0 -11
  433. package/site/dist/assets/ShieldCheckIcon-o6RHYev1.js +0 -1
  434. package/site/dist/assets/SignRequestScreen-BHKv32KR-iQCaBkcz.js +0 -26
  435. package/site/dist/assets/SolanaWalletConnector-C7Lqk-Wz-BUdJJ0ep.js +0 -1
  436. package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-nART-xUU.js +0 -20
  437. package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-Dw9geyK3.js +0 -1
  438. package/site/dist/assets/TodoList-DnyULl18-C8Eyy28X.js +0 -36
  439. package/site/dist/assets/TransactionDetails-e9nesl30-DeEL1JQS.js +0 -109
  440. package/site/dist/assets/TransactionErrorView-BDBNqA_f-Dffuo7I4.js +0 -178
  441. package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-CWLWUiHy.js +0 -31
  442. package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-Bo-tm6wr.js +0 -6
  443. package/site/dist/assets/TurnstileWrapper-B7sNddys-Jwy1tJtm.js +0 -1
  444. package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-gFbSIUhh.js +0 -1
  445. package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-Coy4E1NQ.js +0 -1
  446. package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-D7m70C4b.js +0 -1
  447. package/site/dist/assets/WalletCards-DH1rqayz-Bgp9Fsgs.js +0 -1
  448. package/site/dist/assets/WalletIcon-gKf0gTw6.js +0 -1
  449. package/site/dist/assets/WalletInfoCard-sq_2wgFg-ISBsQt8p.js +0 -29
  450. package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-DG-RuO-F.js +0 -1
  451. package/site/dist/assets/WalletLink-DK5LB5Ha-CXBqCHf3.js +0 -20
  452. package/site/dist/assets/WalletOverflowButton-bfCnp-9T-DP0-PoZL.js +0 -1
  453. package/site/dist/assets/WarningBanner-ZZqCEtZK-2eU4Qo74.js +0 -21
  454. package/site/dist/assets/__vite-browser-external-CitKSmYk.js +0 -1
  455. package/site/dist/assets/_esm-CJe2F7LL.js +0 -7
  456. package/site/dist/assets/_esm-zhBBffjV.js +0 -1
  457. package/site/dist/assets/accounts-Bq8t1wAD.js +0 -1
  458. package/site/dist/assets/accounts-D96UKWkC.js +0 -1
  459. package/site/dist/assets/analytics-mkkvFRju-BRBcadka.js +0 -1
  460. package/site/dist/assets/baseSepolia-DX-qGsik.js +0 -1
  461. package/site/dist/assets/basic-MlZ7f4s9.js +0 -1575
  462. package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-DtOXx-2n.js +0 -1
  463. package/site/dist/assets/ccip-BI9LWBBg.js +0 -1
  464. package/site/dist/assets/ccip-C-59SNEF.js +0 -7
  465. package/site/dist/assets/ccip-y08wK9du.js +0 -1
  466. package/site/dist/assets/chain-DM3oH6Px.js +0 -8
  467. package/site/dist/assets/check-BPgcwEPP.js +0 -1
  468. package/site/dist/assets/chevron-down-BSsbXkK-.js +0 -1
  469. package/site/dist/assets/circle-alert-DWaeLZNj.js +0 -1
  470. package/site/dist/assets/circle-check-big-Chb1ivw9.js +0 -1
  471. package/site/dist/assets/circle-x-AV9Cet0R.js +0 -1
  472. package/site/dist/assets/client-D0IV9lV9.js +0 -2
  473. package/site/dist/assets/client-Dsa7_3V3.js +0 -9
  474. package/site/dist/assets/coinbase-DCPC2L_R-Rs9nVCfm.js +0 -3
  475. package/site/dist/assets/copy-Ckr0AkL6.js +0 -1
  476. package/site/dist/assets/core-zQ1tZtVZ.js +0 -12
  477. package/site/dist/assets/createLucideIcon-IPW50ckY.js +0 -1
  478. package/site/dist/assets/defineChain-CiuCXUZW.js +0 -1
  479. package/site/dist/assets/dijkstra-Drfl93V4.js +0 -1
  480. package/site/dist/assets/dist-BxQqwnue.js +0 -16
  481. package/site/dist/assets/dist-Cm7pNAtL.js +0 -1
  482. package/site/dist/assets/dist-CoS6E-3x.js +0 -1
  483. package/site/dist/assets/dist-Dl07uGq1.js +0 -1
  484. package/site/dist/assets/embed.worker-ugGhEqCV.js +0 -1
  485. package/site/dist/assets/errors-BQ3N-RVt-BLqjTPNR.js +0 -1
  486. package/site/dist/assets/esm-C3DslVJx.js +0 -1
  487. package/site/dist/assets/esm-Ci1ogKuK.js +0 -1
  488. package/site/dist/assets/esm-DXsETz3H.js +0 -1
  489. package/site/dist/assets/esm-n2lWo7kz.js +0 -1
  490. package/site/dist/assets/esm-vs5jNx_Y.js +0 -37
  491. package/site/dist/assets/ethers-zTjbodk5-B7BBFFKf.js +0 -1
  492. package/site/dist/assets/eventemitter3-CL76jPsW.js +0 -1
  493. package/site/dist/assets/external-link-D-uehwM2.js +0 -1
  494. package/site/dist/assets/farcaster-DPlSjvF5-BqTvDXBR.js +0 -1
  495. package/site/dist/assets/features-CYXRa3_m.js +0 -2
  496. package/site/dist/assets/fingerprint-pattern-D8ytA16Q.js +0 -1
  497. package/site/dist/assets/floating-ui.react-dom-DKWOL9UG.js +0 -1
  498. package/site/dist/assets/floating-ui.react-xRkl9O3u.js +0 -1
  499. package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-BVqOKQif.js +0 -1
  500. package/site/dist/assets/formatter-CVbp4SlJ.js +0 -1
  501. package/site/dist/assets/get-entropy-details-for-user-dHRH5Gpi-Dukf7_kJ.js +0 -1
  502. package/site/dist/assets/getChainName-DjpPdUSc-DUyKDrnp.js +0 -1
  503. package/site/dist/assets/getErc20Balance-jXNpFf0N-V2btxzrJ.js +0 -1
  504. package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-CtCwQuGA.js +0 -1
  505. package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-Gx4_wxON.js +0 -1
  506. package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-r2UnDeEy.js +0 -1
  507. package/site/dist/assets/guards-BIW-GiMJ-CHfXo8XI.js +0 -1
  508. package/site/dist/assets/hooks.module-BYZGfwDl.js +0 -1
  509. package/site/dist/assets/hourglass-CPG1HZmf.js +0 -1
  510. package/site/dist/assets/id-UqEwL2BI-CdKXapd-.js +0 -1
  511. package/site/dist/assets/index-BdEw5wyl-ChSJvPZk.js +0 -1
  512. package/site/dist/assets/index-CKdAF_dK.js +0 -8
  513. package/site/dist/assets/index-DvMddJcd-D-4mRLKK.js +0 -12
  514. package/site/dist/assets/index-YiCw0Y_x-BX1zsiqG.js +0 -437
  515. package/site/dist/assets/index.browser-B-i-Lj3J.js +0 -1
  516. package/site/dist/assets/index.browser-BMmUcykv.js +0 -1
  517. package/site/dist/assets/index.es-BmqyoBEM.js +0 -2
  518. package/site/dist/assets/index.es-C1v1or--.js +0 -3
  519. package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-By6r0dVB.js +0 -1
  520. package/site/dist/assets/jsx-runtime-BbDfbRii.js +0 -1
  521. package/site/dist/assets/landmark-CH6LV6F0.js +0 -1
  522. package/site/dist/assets/lib-BsS8z8Lj.js +0 -1
  523. package/site/dist/assets/localBatchGatewayRequest-5YxrERBj.js +0 -32
  524. package/site/dist/assets/lock-DcskI4Bb.js +0 -1
  525. package/site/dist/assets/logger-CsXm3oIv-B0UYpNFI.js +0 -1
  526. package/site/dist/assets/mail-Bs0r5yOi.js +0 -1
  527. package/site/dist/assets/modal-context-CwmSeFcv-DruX9J1E.js +0 -1
  528. package/site/dist/assets/native-BKj27wfc.js +0 -1
  529. package/site/dist/assets/ofetch.CWycOUEr-CHp-crOQ.js +0 -1
  530. package/site/dist/assets/parseAbi-Csg-8t59.js +0 -2
  531. package/site/dist/assets/parseAbiParameters-BWbIMYe4.js +0 -1
  532. package/site/dist/assets/parseEther-CGP3gnf2.js +0 -1
  533. package/site/dist/assets/pkce-DXF0yKjP-Bqz4wAsq.js +0 -1
  534. package/site/dist/assets/preload-helper-BaNbYf_w.js +0 -1
  535. package/site/dist/assets/privy-context-81KmsBw2-CjWGzyg7.js +0 -2
  536. package/site/dist/assets/property-DuZ9DLP4.js +0 -3
  537. package/site/dist/assets/react-DCXkXSrv.js +0 -1
  538. package/site/dist/assets/react-DQnMl2Xv.js +0 -1
  539. package/site/dist/assets/react-DrJ0MmMO.js +0 -1
  540. package/site/dist/assets/react-auth-sHnipzbS.js +0 -1
  541. package/site/dist/assets/react-dom-5dW7aKoP.js +0 -1
  542. package/site/dist/assets/reservoir-x-nGuZkT-BMX127i6.js +0 -1
  543. package/site/dist/assets/roles-32M1l9jI.js +0 -1
  544. package/site/dist/assets/roles-DKPW79Ca.js +0 -1
  545. package/site/dist/assets/rolldown-runtime-BcKkbAw3.js +0 -1
  546. package/site/dist/assets/safe-url-D7SRPu33-CkMedGro.js +0 -1
  547. package/site/dist/assets/secp256k1-C4nzcPo-.js +0 -1
  548. package/site/dist/assets/secp256k1-D92aGNnU.js +0 -1
  549. package/site/dist/assets/secp256k1-DmbwyFau.js +0 -1
  550. package/site/dist/assets/secp256k1-_MleGpqL.js +0 -1
  551. package/site/dist/assets/secp256k1-xl2og-wO.js +0 -1
  552. package/site/dist/assets/serializeAuthorizationList-CX8hGL56.js +0 -1
  553. package/site/dist/assets/serializeSignature-DfxkPnu-.js +0 -2
  554. package/site/dist/assets/sha2-BU_QyRTx.js +0 -1
  555. package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-ByFOTrQK.js +0 -1
  556. package/site/dist/assets/simulateTransaction-CfuOrae4-CMFGDgT_.js +0 -1
  557. package/site/dist/assets/smartphone-CcEZ-XAy.js +0 -1
  558. package/site/dist/assets/src-BBjkfi-Q.js +0 -1
  559. package/site/dist/assets/storage-Ufl800Ne-EalZTH9q.js +0 -9
  560. package/site/dist/assets/stringify-BlDm7tuc.js +0 -21
  561. package/site/dist/assets/stripe.esm-CZRDpc-N.js +0 -2
  562. package/site/dist/assets/styles-BsotlekN-CXEB4Ud9.js +0 -9
  563. package/site/dist/assets/telegram-B-JqnkqZ-RBoY3PLx.js +0 -1
  564. package/site/dist/assets/to-ui-error-DWe-qwS3-DgCO-Y70.js +0 -4
  565. package/site/dist/assets/toViemAccount-B5iDGq1b-DZ1MBqUW.js +0 -2
  566. package/site/dist/assets/transaction-BNTP-bFm-M5tJx8vY.js +0 -1
  567. package/site/dist/assets/transfer-6YztDh-t-BVQkTvG-.js +0 -1
  568. package/site/dist/assets/transformers.web-D4RvOP4-.js +0 -40
  569. package/site/dist/assets/transformers.web-D8W1u_I2.js +0 -49
  570. package/site/dist/assets/triangle-alert-CWjYH75H.js +0 -1
  571. package/site/dist/assets/twitch-5IOe4sIQ-lDtgk0os.js +0 -1
  572. package/site/dist/assets/types-4CuOD23i.js +0 -1
  573. package/site/dist/assets/use-headless-crypto-deposit-Yn-QRLB3-Dn6_8w-Y.js +0 -1
  574. package/site/dist/assets/use-unlink-wallet-BKK4_5Ur-DgsQ75lh.js +0 -1
  575. package/site/dist/assets/useActiveWallet-B-yZYGc6-B6JWREbk.js +0 -123
  576. package/site/dist/assets/useGetSolPrice-x7gfUIHJ-D1hmQfpA.js +0 -1
  577. package/site/dist/assets/useGetTokenPrice-CaoUkb79-ZnbuJ-vP.js +0 -1
  578. package/site/dist/assets/useI18n-C-5n_noF-BcqC76yj.js +0 -1
  579. package/site/dist/assets/useWalletBalance-CZnP5f_f-L3V0jDjL.js +0 -1
  580. package/site/dist/assets/useWallets-X1ndvJ_U-CLwUcevw.js +0 -1
  581. package/site/dist/assets/utils-BkR7EQjg.js +0 -1
  582. package/site/dist/assets/utils-DJhBNOZA.js +0 -1
  583. package/site/dist/assets/utils-DdckVfQr.js +0 -1
  584. package/site/dist/assets/w3m-modal-BMubXAoG.js +0 -1174
  585. package/site/dist/assets/wallet-Bn85Sg2W.js +0 -1
  586. package/site/dist/assets/wallet-connect-BvJtUsDt-Y03hhqFN.js +0 -1
  587. package/site/dist/assets/wallet-uSKqQsgP.js +0 -2
  588. package/site/dist/assets/walletconnect-registry-xxG8XLCb-D1SSFvMp.js +0 -1
  589. package/site/dist/assets/walletconnect-v2-3frQFwbg-Dv6JY_ko.js +0 -12
  590. package/site/dist/assets/x-rlSp9U7W.js +0 -1
package/src/agent/mcp.js CHANGED
@@ -1,50 +1,44 @@
1
1
  #!/usr/bin/env node
2
- // Every Fangorn app's WebMCP tools, behind one stdio MCP server.
2
+ // Every Fangorn app's tools, behind one stdio MCP server.
3
3
  //
4
- // fangorn-mcp [--cdp <url>] [--headed] [--from-block <n>]
4
+ // fangorn-mcp [--from-block <n>]
5
5
  // claude mcp add fangorn -- fangorn-mcp
6
- // claude mcp add fangorn -e FANGORN_MCP_CDP=ws://browser:9222 -- fangorn-mcp
7
6
  //
8
- // WebMCP tools live on `document.modelContext` inside a loaded tab. There is no
9
- // endpoint, so an agent outside the browser cannot reach them, and one MCP
10
- // server per app would mean one registration per app. Instead this server is
11
- // the directory and the browser both:
7
+ // One MCP server for every app, so an agent registers once. It is a directory
8
+ // and a proxy:
12
9
  //
13
10
  // list-apps apps read off the chain (AppAgentChanged → verified cards)
14
- // open-app verify one app's card, open its page in a tab, and add its
15
- // tools to this server as `<app>__<tool>` (tools/list_changed)
11
+ // open-app verify one app's card and add its tools to this server as
12
+ // `<app>__<tool>` (tools/list_changed)
16
13
  // call-app-tool the same call by name, for clients that ignore list_changed
17
14
  //
18
- // One browser, one tab per opened app: a WebMCP browser at --cdp, or else a
19
- // local Chrome with WebMCP on, headless unless --headed. Calls
20
- // are relayed to the tab's own `modelContext.executeTool`, so the tools, their
21
- // schemas and their answers are the page's, and queries still run in the tab.
22
- // A local Chrome's profile persists (~/.cache/westmarch-mcp), so a page's
23
- // downloads, such as an embedding model, are fetched once. A tab or browser that
24
- // dies is reopened on the next call.
15
+ // An app's tools are its own MCP server's (the card's `mcp`, the app's Worker at
16
+ // /mcp), relayed. The Worker alone reads the app's lens from R2, so nothing is
17
+ // downloaded here and access is the app's to gate.
18
+ // A private app's paid tools answer with x402's PaymentRequired. With FANGORN_MCP_WALLET_KEY set,
19
+ // this server pays: a pass when the card sells one at or under FANGORN_MCP_MAX_PASS (USDC; unset,
20
+ // never), else that one call at or under FANGORN_MCP_MAX_PRICE (default 0.10). Without a wallet the
21
+ // price is handed back to the agent, to say to the person.
25
22
 
26
- import { spawn } from "node:child_process";
27
- import { mkdirSync, readFileSync, existsSync, rmSync, writeFileSync, renameSync } from "node:fs";
28
- import { createHash } from "node:crypto";
29
23
  import net from "node:net";
30
24
  import { homedir } from "node:os";
31
25
  import { createInterface } from "node:readline";
32
26
  import { APP_EXTENSION, listApps, toApp } from "../discover/apps.js";
33
27
 
34
- // The current AppRegistry's first event on Arbitrum Sepolia. A reader's
35
- // default, not deployment config: pass --from-block for another deployment.
36
- const DEFAULT_FROM_BLOCK = 311637349n;
37
28
  const log = (...a) => console.error("[fangorn-mcp]", ...a); // stdout is the protocol
38
29
  // FANGORN_MCP_TRACE=1: step timings on stderr, for finding where an answer waits.
39
30
  const T0 = performance.now();
40
31
  const trace = process.env.FANGORN_MCP_TRACE ? (what) => log(`${Math.round(performance.now() - T0)}ms ${what}`) : () => {};
41
32
 
33
+ // FANGORN_NETWORK: the SDK's network name ("baseSepolia"); unset, its default.
34
+ const network = async () => (await import("../publish/view.js")).network();
35
+
42
36
  let client;
43
37
  async function fangorn() {
44
38
  if (!client) {
45
- const [{ Fangorn, FangornConfig }, { generatePrivateKey }] = await Promise.all([
39
+ const [{ Fangorn }, { generatePrivateKey }] = await Promise.all([
46
40
  import("@fangorn-network/sdk"), import("viem/accounts")]);
47
- client = Fangorn.create({ privateKey: generatePrivateKey(), config: FangornConfig }); // reads only
41
+ client = Fangorn.create({ privateKey: generatePrivateKey(), config: await network() }); // reads only
48
42
  // list-apps verifies every card and open-app verifies one again: once a minute is enough.
49
43
  const verify = client.discoverApp.bind(client), seen = new Map();
50
44
  client.discoverApp = (url) => {
@@ -58,62 +52,66 @@ async function fangorn() {
58
52
  return client;
59
53
  }
60
54
 
61
- /** A card URL → the verified card and the page to open. A plain A2A card (no
62
- * Fangorn extension) opens unverified: the caller asked for it by URL. */
55
+ /** A card URL → its app's MCP endpoint (the card's `mcp`), once the card verifies on chain. */
63
56
  async function resolveCard(cardUrl) {
64
57
  const card = await (await fetch(cardUrl)).json();
65
- const fangornApp = card.capabilities?.extensions?.some((e) => e.uri === APP_EXTENSION);
66
- // Views only from a verified card, and only http(s) ones (toApp filters).
67
- const app = fangornApp ? toApp(await (await fangorn()).discoverApp(cardUrl), cardUrl) : null;
68
- const page = new URL(card.url);
69
- if (page.protocol !== "https:" && page.protocol !== "http:") throw new Error(`card.url is not http(s): ${card.url}`);
70
- return { card, page: page.toString(), verified: fangornApp, views: app?.views ?? [], paid: app?.paid ?? null };
58
+ if (!card.capabilities?.extensions?.some((e) => e.uri === APP_EXTENSION)) throw new Error(`${cardUrl} is not a Fangorn app card`);
59
+ const { mcp } = toApp(await (await fangorn()).discoverApp(cardUrl), cardUrl);
60
+ return { card, mcp };
71
61
  }
72
62
 
73
- // ── the network ─────────────────────────────────────────────────────────────
74
- // Every byte an answer waits on, cached where it is safe to:
75
- // - a content-addressed file (`…-<12 hex>.<ext>`, every shard) never changes,
76
- // so it is kept on disk forever. shard.js still checks it against the
77
- // manifest's sha256, so a bad cache entry fails loudly, not silently.
78
- // - catalogs, manifests and cards change on a rebake: held for a minute, so
79
- // one search (or resolving then verifying a card) does not fetch each twice.
80
- const CACHE = `${homedir()}/.cache/fangorn-mcp`;
81
- /** Stale-while-revalidate from disk: the last copy at once, a fresh one fetched
82
- * behind it for next time. Only for reads where stale is harmless. */
83
- function staleFetch(fetcher) {
84
- mkdirSync(`${CACHE}/stale`, { recursive: true });
85
- return async (url) => {
86
- const f = `${CACHE}/stale/${createHash("sha256").update(url).digest("hex")}`;
87
- const refresh = fetcher(url).then(async (r) => {
88
- if (!r.ok) return r;
89
- const b = new Uint8Array(await r.arrayBuffer());
90
- writeFileSync(`${f}.tmp`, b); renameSync(`${f}.tmp`, f);
91
- return new Response(b);
92
- });
93
- if (existsSync(f)) { refresh.catch(() => {}); return new Response(readFileSync(f)); }
94
- return refresh;
63
+ /** An app's own MCP server over streamable HTTP → `{ tools, call }`.
64
+ * The app's Worker is stateless (one JSON body per POST); a session id or an SSE
65
+ * reply from any other server is followed too. */
66
+ export async function remoteTools(url, fetcher = fetch, { access = null, wallet = process.env.FANGORN_MCP_WALLET_KEY,
67
+ maxCall = process.env.FANGORN_MCP_MAX_PRICE ?? "0.10", maxPass = process.env.FANGORN_MCP_MAX_PASS } = {}) {
68
+ let id = 0, session, bearer;
69
+ const rpc = async (method, params) => {
70
+ const r = await fetcher(url, { method: "POST", body: JSON.stringify({ jsonrpc: "2.0", id: ++id, method, params }),
71
+ headers: { "content-type": "application/json", accept: "application/json, text/event-stream", ...(session && { "mcp-session-id": session }),
72
+ ...(bearer && { authorization: `Bearer ${bearer}` }) } });
73
+ session ??= r.headers.get("mcp-session-id") ?? undefined;
74
+ let body = await r.text();
75
+ if (!r.ok) throw new Error(`${url}: HTTP ${r.status} ${body.slice(0, 200)}`);
76
+ if (r.headers.get("content-type")?.includes("text/event-stream")) body = body.split("\n").filter((l) => l.startsWith("data:")).pop()?.slice(5) ?? "";
77
+ const m = JSON.parse(body);
78
+ if (m.error) throw new Error(`${url}: ${m.error.message}`);
79
+ return m.result;
95
80
  };
81
+ await rpc("initialize", { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "fangorn-mcp", version: "0.1.0" } });
82
+ const { tools } = await rpc("tools/list", {});
83
+ const usdc = (n) => BigInt(Math.round(Number(n) * 10 ** (access?.decimals ?? 6)));
84
+ const call = async (name, args) => {
85
+ const params = { name, arguments: args ?? {} };
86
+ const r = await rpc("tools/call", params);
87
+ const asked = r?.isError && r.structuredContent?.x402Version === 2 ? r.structuredContent : null;
88
+ if (!asked) return r;
89
+ if (!wallet) return { ...r, content: [...r.content, { type: "text", text: "This server has no wallet (FANGORN_MCP_WALLET_KEY), so nothing was paid: tell the person the price." }] };
90
+ const x = await import("./x402.js");
91
+ const account = (await import("viem/accounts")).privateKeyToAccount(`0x${wallet.trim().replace(/^0x/i, "")}`); // a key file may lack 0x
92
+ if (access && maxPass != null && BigInt(access.pass) <= usdc(maxPass)) {
93
+ bearer = (await x.buyPass(access, { account, fetchImpl: fetcher })).token;
94
+ return rpc("tools/call", params);
95
+ }
96
+ const payment = await x.signPayment(x.choose(asked.accepts, { maxPrice: usdc(maxCall) }), account, { resource: asked.resource });
97
+ return rpc("tools/call", { ...params, _meta: { "x402/payment": payment } });
98
+ };
99
+ return { tools, call };
96
100
  }
97
101
 
102
+ // ── the network ─────────────────────────────────────────────────────────────
103
+ // Catalogs, manifests and cards change on a rebake: held for a minute, so one
104
+ // search (or resolving then verifying a card) does not fetch each twice.
105
+ const CACHE = `${homedir()}/.cache/fangorn-mcp`; // the embedding model, for find-apps
98
106
  function cachingFetch(real = globalThis.fetch) {
99
- mkdirSync(`${CACHE}/blobs`, { recursive: true });
100
107
  const memo = new Map();
101
108
  return async (input, init) => {
102
109
  const url = String(input?.url ?? input);
103
110
  if ((init?.method ?? input?.method ?? "GET") !== "GET" || !/^https?:/.test(url)) return real(input, init);
104
111
  const path = new URL(url).pathname;
105
- if (/-[0-9a-f]{12}\.[a-z.]+$/.test(path)) {
106
- const f = `${CACHE}/blobs/${createHash("sha256").update(url).digest("hex")}`;
107
- if (existsSync(f)) return new Response(readFileSync(f));
108
- const r = await real(input, init);
109
- if (!r.ok) return r;
110
- const b = new Uint8Array(await r.arrayBuffer());
111
- writeFileSync(`${f}.tmp`, b); renameSync(`${f}.tmp`, f); // never a torn file
112
- return new Response(b, { headers: r.headers });
113
- }
114
112
  // A card, catalog or manifest is small: 8s without one means the host is
115
113
  // down, and a dead card in the directory must not stall a listing for a
116
- // TCP timeout. Shards get no deadline; a big file on a slow link is legitimate.
114
+ // TCP timeout.
117
115
  init = { ...init, signal: init?.signal ?? AbortSignal.timeout(8000) };
118
116
  if (/\/cdn\/catalog$|\/manifest$|\/agent-card\.json$/.test(path)) {
119
117
  const hit = memo.get(url);
@@ -128,140 +126,6 @@ function cachingFetch(real = globalThis.fetch) {
128
126
  };
129
127
  }
130
128
 
131
- // ── the browser ─────────────────────────────────────────────────────────────
132
- // Anything that speaks the Chrome DevTools Protocol and has WebMCP: a headless
133
- // Chromium service, a hosted browser, or the local Chrome. `--cdp` (or
134
- // FANGORN_MCP_CDP) names it as http(s)://host:port or a ws(s):// browser
135
- // endpoint. Without it, a local Chrome is reused if one is already serving
136
- // this profile (another session's), else launched.
137
- //
138
- // Everything goes over the one browser-level WebSocket (Target.* plus flat
139
- // sessions). That is the endpoint every CDP host exposes, where the per-tab
140
- // /json HTTP routes are not.
141
-
142
- const PROFILE = `${homedir()}/.cache/westmarch-mcp`;
143
-
144
- /** An http(s) DevTools address → its browser WebSocket, reached via the host we were given. */
145
- async function browserWs(http) {
146
- const v = await (await fetch(new URL("/json/version", http), { signal: AbortSignal.timeout(3000) })).json();
147
- const ws = new URL(v.webSocketDebuggerUrl), base = new URL(http);
148
- ws.host = base.host; // the service reports its own view of itself
149
- if (base.protocol === "https:") ws.protocol = "wss:";
150
- return ws.toString();
151
- }
152
-
153
- async function localChrome({ headed }) {
154
- mkdirSync(PROFILE, { recursive: true });
155
- const portFile = `${PROFILE}/DevToolsActivePort`;
156
- if (existsSync(portFile)) {
157
- const ws = await browserWs(`http://127.0.0.1:${readFileSync(portFile, "utf-8").split("\n")[0]}`).catch(() => null);
158
- if (ws) { log("reusing the Chrome already serving this profile"); return { ws }; }
159
- rmSync(portFile, { force: true }); // stale: that Chrome is gone
160
- }
161
- const bin = process.env.CHROME ?? "google-chrome";
162
- const proc = spawn(bin, [
163
- ...(headed ? [] : ["--headless=new"]),
164
- "--enable-features=WebMCP", "--remote-debugging-port=0", "--no-first-run",
165
- "--no-default-browser-check", `--user-data-dir=${PROFILE}`, "about:blank",
166
- ], { stdio: "ignore" });
167
- const failed = new Promise((_, j) => proc.on("error", (e) => j(new Error(
168
- `no browser: cannot launch ${bin} (${e.code}). Point --cdp / FANGORN_MCP_CDP at a WebMCP browser, or set CHROME.`))));
169
- // 30s: a cold start on a loaded machine or CI box has taken 16s.
170
- for (let i = 0; i < 300; i++) {
171
- await Promise.race([new Promise((r) => setTimeout(r, 100)), failed]);
172
- if (existsSync(portFile)) return { ws: await browserWs(`http://127.0.0.1:${readFileSync(portFile, "utf-8").split("\n")[0]}`), proc };
173
- }
174
- proc.kill();
175
- throw new Error(`${bin} did not start`);
176
- }
177
-
178
- let conn;
179
- /** The browser connection, opened once and reopened after it drops. */
180
- function browser(opts) {
181
- return conn ??= (async () => {
182
- const { cdp } = opts;
183
- const { ws: url, proc } = !cdp ? await localChrome(opts)
184
- : /^wss?:/.test(cdp) ? { ws: cdp } : { ws: await browserWs(cdp) };
185
- const ws = new WebSocket(url);
186
- await new Promise((r, j) => { ws.onopen = r; ws.onerror = () => j(new Error(`cannot connect to the browser at ${url}`)); });
187
- let id = 0; const pending = new Map(), dead = new Set();
188
- ws.onmessage = (m) => {
189
- const d = JSON.parse(m.data);
190
- if (d.method === "Target.detachedFromTarget") dead.add(d.params.sessionId);
191
- if (d.id !== undefined) { pending.get(d.id)?.(d); pending.delete(d.id); }
192
- };
193
- ws.onclose = () => { conn = null; for (const r of pending.values()) r({ error: { message: "browser connection closed" } }); };
194
- const send = (method, params = {}, sessionId) => new Promise((res, rej) => {
195
- if (ws.readyState !== WebSocket.OPEN) return rej(new Error("browser connection closed"));
196
- pending.set(++id, (d) => (d.error ? rej(new Error(d.error.message)) : res(d.result)));
197
- ws.send(JSON.stringify({ id, method, params, ...(sessionId && { sessionId }) }));
198
- });
199
- const tabs = new Set();
200
- // Close what we opened. A shared or remote browser outlives this process.
201
- const bye = async () => {
202
- await Promise.race([Promise.all([...tabs].map((t) => send("Target.closeTarget", { targetId: t }).catch(() => {}))),
203
- new Promise((r) => setTimeout(r, 500))]);
204
- // A local Chrome may be serving another session: leave it running
205
- // while anyone else has a tab open; the last one out closes it.
206
- const others = await Promise.race([send("Target.getTargets").then((r) => r.targetInfos.filter((t) => t.type === "page" && t.url !== "about:blank").length).catch(() => 0),
207
- new Promise((r) => setTimeout(() => r(0), 500))]);
208
- // Never a --cdp browser: that one is somebody's service.
209
- if (!cdp && !others) await Promise.race([send("Browser.close").catch(() => {}), new Promise((r) => setTimeout(r, 500))]);
210
- proc?.kill();
211
- process.exit(0);
212
- };
213
- process.once("SIGINT", bye); process.once("SIGTERM", bye); process.stdin.once("end", bye);
214
- log(`browser: ${cdp ?? (proc ? "launched local Chrome" : "local Chrome")}`);
215
- return { send, dead, tabs };
216
- })().catch((e) => { conn = null; throw e; });
217
- }
218
-
219
- /** A new tab on `page`; returns `ev(expr)`, which evaluates in it. */
220
- async function openTab(page, opts) {
221
- const { send, dead, tabs } = await browser(opts);
222
- const { targetId } = await send("Target.createTarget", { url: page });
223
- tabs.add(targetId);
224
- const { sessionId } = await send("Target.attachToTarget", { targetId, flatten: true });
225
- return async (expression) => {
226
- if (dead.has(sessionId)) throw new Error(`tab closed: ${page}`);
227
- const r = await send("Runtime.evaluate", { expression, awaitPromise: true, returnByValue: true }, sessionId)
228
- .catch((e) => { throw new Error(`tab closed: ${page} (${e.message})`); });
229
- if (r.exceptionDetails) throw new Error(r.exceptionDetails.exception?.description ?? r.exceptionDetails.text);
230
- return r.result.value;
231
- };
232
- }
233
-
234
- /** The tab's tools in MCP's shape. Waits for the page to register them. */
235
- async function tabTools(ev) {
236
- let hasWebMCP = false;
237
- for (let i = 0; i < 150; i++) {
238
- const got = await ev(`(async () => {
239
- const mc = document.modelContext;
240
- if (!mc?.getTools) return { webmcp: false, loaded: location.protocol.startsWith("http") && document.readyState === "complete" };
241
- return { webmcp: true, tools: (await mc.getTools()).map((t) => ({ name: t.name, description: t.description, inputSchema: t.inputSchema })) };
242
- })()`).catch(() => null);
243
- hasWebMCP ||= !!got?.webmcp;
244
- // modelContext is there from the first script or never; no need to wait out the page.
245
- if (got && !got.webmcp && got.loaded) break;
246
- if (got?.tools?.length) return got.tools.map((t) => ({ ...t, inputSchema: t.inputSchema ? JSON.parse(t.inputSchema) : { type: "object" } }));
247
- await new Promise((r) => setTimeout(r, 200));
248
- }
249
- throw new Error(hasWebMCP
250
- ? "the page registered no WebMCP tools in 30s (is card.url the page that registers them?)"
251
- : "this browser has no WebMCP (document.modelContext.getTools): it needs Chrome 150+ with --enable-features=WebMCP, or a Chromium built with it");
252
- }
253
-
254
- /** One call, relayed. WebMCP takes the arguments as a JSON string and returns one. */
255
- async function tabCall(ev, name, args) {
256
- const out = await ev(`document.modelContext.getTools().then((ts) => {
257
- const t = ts.find((t) => t.name === ${JSON.stringify(name)});
258
- if (!t) throw new Error("no tool " + ${JSON.stringify(name)});
259
- return document.modelContext.executeTool(t, ${JSON.stringify(JSON.stringify(args ?? {}))});
260
- })`);
261
- try { const r = JSON.parse(out); if (Array.isArray(r?.content)) return r; } catch {}
262
- return { content: [{ type: "text", text: String(out) }] };
263
- }
264
-
265
129
  /** JSON-RPC over newline-delimited stdio. Returns `notify` for server → client messages. */
266
130
  export function serve(handlers, { input = process.stdin, output = process.stdout } = {}) {
267
131
  const send = (m) => output.write(JSON.stringify({ jsonrpc: "2.0", ...m }) + "\n");
@@ -282,7 +146,7 @@ const slug = (name) => String(name).toLowerCase().replace(/[^a-z0-9-]+/g, "-").r
282
146
 
283
147
  const META = [
284
148
  { name: "list-apps",
285
- description: "List the Fangorn apps registered on chain whose agent cards verify: name, description, card URL, and the WebMCP tools each page offers. Filter with `query`. Call open-app on one to use its tools.",
149
+ description: "List the Fangorn apps registered on chain whose agent cards verify: name, description, card URL, and its appId. Filter with `query`. Call open-app on one to use its tools.",
286
150
  inputSchema: { type: "object", properties: { query: { type: "string", description: "Case-insensitive match on name or description" } } } },
287
151
  { name: "find-apps",
288
152
  description: "Find Fangorn apps for a question, ranked by what their data is about (e.g. \"where can I learn about weather?\", \"music\"). Each app carries its site, agent card, ERC-8004 agent with an 8004scan link, ERC-8004 reputation (feedback count and average), record count and bound block. Only apps whose cards verify on chain. `relevant: true` marks the ones worth opening; the rest are sorted, not relevant. With no query, lists every app. Then open-app.",
@@ -290,8 +154,8 @@ const META = [
290
154
  query: { type: "string", description: "What the person is looking for, in their words" },
291
155
  limit: { type: "integer", minimum: 1, maximum: 50, default: 10 } } } },
292
156
  { name: "open-app",
293
- description: "Verify an app's card against the chain and add its tools to this server as `<app>__<tool>`. An app that publishes views gets fast data tools (describe, search, get, similar, count, browse) with no browser. `page: true` also opens the app's page in a browser for its own WebMCP tools (slower). `app` is a name from list-apps, an appId, or a card URL.",
294
- inputSchema: { type: "object", properties: { app: { type: "string" }, page: { type: "boolean", description: "Also load the page's own WebMCP tools in a browser" } }, required: ["app"] } },
157
+ description: "Verify an app's card against the chain and add its tools to this server as `<app>__<tool>`. The tools are the app's own MCP server's (typically describe, search, get, similar, count, browse). `app` is a name from list-apps, an appId, or a card URL.",
158
+ inputSchema: { type: "object", properties: { app: { type: "string" } }, required: ["app"] } },
295
159
  { name: "call-app-tool",
296
160
  description: "Call one tool of an opened app. Same as calling `<app>__<tool>` directly.",
297
161
  inputSchema: { type: "object", properties: { app: { type: "string" }, tool: { type: "string" }, arguments: { type: "object" } }, required: ["app", "tool"] } },
@@ -302,52 +166,34 @@ const META = [
302
166
  * findApps() → { apps: [{ name, desc, card, appId }], rejected }
303
167
  * exploreApps(query) → { apps: ranked explore.js entries, ranked_by }
304
168
  * findByName(name) → { card, appId } | null (optional: a direct registry read)
305
- * resolveCard(url) → { card, page, verified, views }
306
- * viewTools(app) → { tools, call(name, args) } | null (no browser)
307
- * openTab(page) → ev
308
- * tabTools(ev), tabCall(ev, name, args)
169
+ * resolveCard(url) → { card, mcp }
170
+ * remoteTools(url) → { tools, call(name, args) } (the app's own MCP server)
309
171
  * notify(method) set after serve()
310
172
  */
311
173
  export function handlers(deps) {
312
- const open = new Map(); // slug → { name, card, verified, page, views?, pages?, tools }
174
+ const open = new Map(); // slug → { slug, name, card, appId, tools, call }
313
175
 
314
176
  const findOpen = (app) => open.get(slug(app)) ?? [...open.values()].find((o) => o.card === app || o.appId === app);
315
- const retool = (o) => {
316
- const taken = new Set(o.views?.tools.map((t) => t.name));
317
- // A page tool that shares a data tool's name is kept, under `page-<name>`.
318
- o.pageNames = new Map((o.pageTools ?? []).map((t) => [taken.has(t.name) ? `page-${t.name}` : t.name, t.name]));
319
- o.tools = [...(o.views?.tools ?? []), ...(o.pageTools ?? []).map((t) => ({ ...t, name: taken.has(t.name) ? `page-${t.name}` : t.name }))];
320
- };
321
- async function openPage(o) {
322
- o.ev = await deps.openTab(o.page);
323
- o.pageTools = await deps.tabTools(o.ev);
324
- }
325
177
 
326
- async function openApp(app, { page = false } = {}) {
178
+ async function openApp(app) {
327
179
  const hit = findOpen(app);
328
- if (hit && (hit.ev || !page)) return hit;
329
- let o = hit;
330
- if (!o) {
331
- let cardUrl = app, appId;
332
- if (!/^https?:\/\//.test(app)) {
333
- // One registry read when the name is the app's own; the scan only when it is not.
334
- trace(`open ${app}: lookup`);
335
- const a = await deps.findByName?.(app)
336
- ?? (await deps.findApps()).apps.find((x) => x.appId === app || slug(x.name) === slug(app));
337
- if (!a) throw new Error(`no verified app named ${JSON.stringify(app)}; see list-apps`);
338
- ({ card: cardUrl, appId } = a);
339
- }
340
- trace(`open ${app}: resolve ${cardUrl}`);
341
- const { card, page: url, verified, views, paid } = await deps.resolveCard(cardUrl);
342
- trace(`open ${app}: verified`);
343
- let s = slug(card.name ?? app);
344
- while (open.has(s)) s += "-";
345
- o = { slug: s, name: card.name, card: cardUrl, appId, verified, page: url,
346
- views: deps.viewTools?.({ name: card.name, desc: card.description, views, paid }) ?? null };
180
+ if (hit) return hit;
181
+ let cardUrl = app, appId;
182
+ if (!/^https?:\/\//.test(app)) {
183
+ // One registry read when the name is the app's own; the scan only when it is not.
184
+ trace(`open ${app}: lookup`);
185
+ const a = await deps.findByName?.(app)
186
+ ?? (await deps.findApps()).apps.find((x) => x.appId === app || slug(x.name) === slug(app));
187
+ if (!a) throw new Error(`no verified app named ${JSON.stringify(app)}; see list-apps`);
188
+ ({ card: cardUrl, appId } = a);
347
189
  }
348
- // The browser only when asked, or when there is no other way in.
349
- if (page || !o.views) await openPage(o);
350
- retool(o);
190
+ trace(`open ${app}: resolve ${cardUrl}`);
191
+ const { card, mcp } = await deps.resolveCard(cardUrl);
192
+ if (!mcp) throw new Error(`${card.name ?? cardUrl} has no MCP server (its card has no \`mcp\`)`);
193
+ let s = slug(card.name ?? app);
194
+ while (open.has(s)) s += "-";
195
+ const access = card.capabilities?.extensions?.find((e) => e.uri === APP_EXTENSION)?.params?.access ?? null;
196
+ const o = { slug: s, name: card.name, card: cardUrl, appId, ...await deps.remoteTools(mcp, { access }) };
351
197
  trace(`open ${app}: ready`);
352
198
  open.set(o.slug, o);
353
199
  deps.notify?.("notifications/tools/list_changed");
@@ -357,18 +203,8 @@ export function handlers(deps) {
357
203
  async function call(app, tool, args) {
358
204
  const o = findOpen(app);
359
205
  if (!o) throw new Error(`${app} is not open; call open-app first`);
360
- if (!o.pageNames?.has(tool)) {
361
- if (o.views?.tools.some((t) => t.name === tool)) return o.views.call(tool, args);
362
- throw new Error(`${o.slug} has no tool ${tool}${o.ev ? "" : " (its page tools load with open-app page: true)"}`);
363
- }
364
- const name = o.pageNames.get(tool);
365
- try { return await deps.tabCall(o.ev, name, args); }
366
- catch (e) {
367
- if (!/tab closed/.test(e.message)) throw e;
368
- // The tab or the whole browser went away. Reopen once; the tools keep their names.
369
- await openPage(o);
370
- return deps.tabCall(o.ev, name, args);
371
- }
206
+ if (!o.tools.some((t) => t.name === tool)) throw new Error(`${o.slug} has no tool ${tool}`);
207
+ return o.call(tool, args);
372
208
  }
373
209
 
374
210
  const run = {
@@ -378,7 +214,7 @@ export function handlers(deps) {
378
214
  return text({
379
215
  apps: apps.filter((a) => !q || `${a.name} ${a.desc}`.toLowerCase().includes(q)).map((a) => ({
380
216
  app: slug(a.name), name: a.name, description: a.desc, card: a.card, appId: a.appId,
381
- tools: a.tools, open: open.has(slug(a.name)),
217
+ open: open.has(slug(a.name)),
382
218
  })),
383
219
  unverified: rejected.length,
384
220
  });
@@ -388,10 +224,9 @@ export function handlers(deps) {
388
224
  return text({ query: query ?? null, ranked_by, apps: apps.slice(0, Math.min(50, Math.max(1, limit)))
389
225
  .map((a) => ({ ...a, open: open.has(a.app) })) });
390
226
  },
391
- "open-app": async ({ app, page }) => {
392
- const o = await openApp(app, { page });
393
- return text({ app: o.slug, name: o.name, verified: o.verified,
394
- data_tools: !!o.views, page_tools: o.ev ? o.page : false,
227
+ "open-app": async ({ app }) => {
228
+ const o = await openApp(app);
229
+ return text({ app: o.slug, name: o.name, card: o.card,
395
230
  call_as: `${o.slug}__<tool>, or call-app-tool`, tools: o.tools });
396
231
  },
397
232
  "call-app-tool": async ({ app, tool, arguments: args }) => call(app, tool, args),
@@ -402,7 +237,7 @@ export function handlers(deps) {
402
237
  protocolVersion: p.protocolVersion ?? "2025-06-18",
403
238
  capabilities: { tools: { listChanged: true } },
404
239
  serverInfo: { name: "fangorn-mcp", version: "0.1.0" },
405
- instructions: "Fangorn apps are static sites anchored on chain. list-apps to find one, open-app to load it, then call its tools as <app>__<tool>. Start with <app>__describe when it exists.",
240
+ instructions: "Fangorn apps are anchored on chain and each serves its own MCP. list-apps to find one, open-app to load it, then call its tools as <app>__<tool>. Start with <app>__describe when it exists.",
406
241
  }),
407
242
  ping: async () => ({}),
408
243
  "tools/list": async () => ({ tools: [
@@ -427,15 +262,22 @@ if (process.argv[2] === "--selfcheck") {
427
262
  const input = new PassThrough(), output = new PassThrough();
428
263
  const replies = [];
429
264
  createInterface({ input: output }).on("line", (l) => replies.push(JSON.parse(l)));
265
+ const posts = [];
266
+ // The app's Worker: initialize, tools/list, tools/call over JSON-RPC POSTs.
267
+ const remote = await remoteTools("https://k.test/mcp", async (url, init) => {
268
+ const m = JSON.parse(init.body);
269
+ posts.push(m.method);
270
+ const result = m.method === "tools/list" ? { tools: [{ name: "search" }] }
271
+ : m.method === "tools/call" ? text({ via: "remote", ...m.params }) : {};
272
+ return new Response(JSON.stringify({ jsonrpc: "2.0", id: m.id, result }), { headers: { "content-type": "application/json" } });
273
+ });
430
274
  let opened = 0;
431
275
  const deps = {
432
- findApps: async () => ({ apps: [{ name: "Kings Foil", desc: "trials", card: "https://k.test/card", appId: "0xk", tools: ["greet"] }], rejected: [{}] }),
276
+ findApps: async () => ({ apps: [{ name: "Kings Foil", desc: "trials", card: "https://k.test/card", appId: "0xk" },
277
+ { name: "Bare", desc: "", card: "https://b.test/card", appId: "0xb" }], rejected: [{}] }),
433
278
  exploreApps: async (q) => ({ ranked_by: q ? "meaning" : null, apps: [{ app: "kings-foil", name: "Kings Foil", relevant: true }, { app: "b", name: "B", relevant: false }] }),
434
- resolveCard: async () => ({ card: { name: "Kings Foil" }, page: "https://k.test/p", verified: true }),
435
- openTab: async () => (opened++ ? "ev" : "dead"), // the first tab dies
436
- tabTools: async () => [{ name: "greet", description: "Hi.", inputSchema: { type: "object" } }],
437
- tabCall: async (ev, name, args) => (name === "boom" ? Promise.reject(new Error("no tool boom"))
438
- : ev === "dead" ? Promise.reject(new Error("tab closed: x")) : text({ ev, name, args })),
279
+ resolveCard: async (url) => (url.includes("b.test") ? { card: { name: "Bare" }, mcp: null } : { card: { name: "Kings Foil" }, mcp: "https://k.test/mcp" }),
280
+ remoteTools: async () => (opened++, remote),
439
281
  };
440
282
  deps.notify = serve(handlers(deps), { input, output });
441
283
  const rpc = (id, method, params) => input.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
@@ -445,10 +287,10 @@ if (process.argv[2] === "--selfcheck") {
445
287
  const body = (id) => JSON.parse(res(id).result.content[0].text);
446
288
  const assert = (c, m) => { if (!c) throw new Error(m); };
447
289
 
448
- rpc(1, "initialize", {}); rpc(2, "tools/list"); call(3, "list-apps", { query: "TRIAL" }); call(4, "kings-foil__greet"); await wait();
290
+ rpc(1, "initialize", {}); rpc(2, "tools/list"); call(3, "list-apps", { query: "TRIAL" }); call(4, "kings-foil__search"); await wait();
449
291
  assert(res(1).result.capabilities.tools.listChanged, "advertises list_changed");
450
292
  assert(res(2).result.tools.length === 4, "only the meta tools before anything is open");
451
- assert(body(3).apps[0].app === "kings-foil" && body(3).unverified === 1, "list-apps filters and slugs");
293
+ assert(body(3).apps.length === 1 && body(3).apps[0].app === "kings-foil" && body(3).unverified === 1, "list-apps filters and slugs");
452
294
  assert(res(4).result.isError && /not open/.test(res(4).result.content[0].text), "an unopened app's tool is an error");
453
295
 
454
296
  call(30, "find-apps", { query: "trials", limit: 1 }); await wait();
@@ -456,40 +298,44 @@ if (process.argv[2] === "--selfcheck") {
456
298
 
457
299
  call(5, "open-app", { app: "Kings Foil" }); await wait();
458
300
  call(6, "open-app", { app: "https://k.test/card" }); await wait();
459
- assert(body(5).tools[0].name === "greet" && opened === 1, "open once, by name or by card URL");
460
- call(50, "kings-foil__greet", { who: "b" }); await wait();
461
- assert(body(50).ev === "ev" && opened === 2, "a dead tab is reopened and the call retried");
301
+ assert(body(5).tools[0].name === "search" && opened === 1, "open once, by name or by card URL");
462
302
  assert(replies.some((r) => r.method === "notifications/tools/list_changed"), "opening notifies");
463
- rpc(7, "tools/list"); call(8, "kings-foil__greet", { who: "a" }); call(9, "call-app-tool", { app: "kings-foil", tool: "greet" });
464
- call(10, "call-app-tool", { app: "kings-foil", tool: "boom" }); call(11, "open-app", { app: "nope" }); rpc(12, "nope"); await wait();
465
- assert(res(7).result.tools.some((t) => t.name === "kings-foil__greet"), "opened tools are listed under the app");
466
- assert(body(8).args.who === "a" && body(9).name === "greet", "both call paths reach the tab");
303
+ rpc(7, "tools/list"); call(8, "kings-foil__search", { query: "x" }); call(9, "call-app-tool", { app: "kings-foil", tool: "search" });
304
+ call(10, "call-app-tool", { app: "kings-foil", tool: "boom" }); call(11, "open-app", { app: "nope" }); call(13, "open-app", { app: "Bare" }); rpc(12, "nope"); await wait();
305
+ assert(res(7).result.tools.some((t) => t.name === "kings-foil__search"), "opened tools are listed under the app");
306
+ assert(body(8).via === "remote" && body(8).arguments.query === "x" && body(9).name === "search", "both call paths reach the app's server");
307
+ assert(posts.join() === "initialize,tools/list,tools/call,tools/call", `initialize, list, then calls: ${posts}`);
467
308
  assert(res(10).result.isError && res(11).result.isError, "failures are tool errors");
309
+ assert(res(13).result.isError && /no MCP server/.test(res(13).result.content[0].text), "an app without `mcp` cannot open");
468
310
  assert(res(12).error.code === -32601, "unknown method");
469
-
470
- // An app with views: data tools, no browser, until page: true.
471
- {
472
- const out2 = new PassThrough(), in2 = new PassThrough(), r2 = [];
473
- createInterface({ input: out2 }).on("line", (l) => r2.push(JSON.parse(l)));
474
- let tabs = 0;
475
- const d2 = { ...deps,
476
- resolveCard: async () => ({ card: { name: "Kings Foil" }, page: "https://k.test/p", verified: true, views: ["https://k.test/v"] }),
477
- viewTools: (app) => ({ tools: [{ name: "search" }, { name: "greet" }], call: async (n, a) => text({ via: "views", n, a, views: app.views }) }),
478
- openTab: async () => (tabs++, "ev"),
479
- };
480
- d2.notify = serve(handlers(d2), { input: in2, output: out2 });
481
- const q = (id, name, args) => in2.write(JSON.stringify({ jsonrpc: "2.0", id, method: "tools/call", params: { name, arguments: args } }) + "\n");
482
- const got = (id) => r2.find((r) => r.id === id)?.result;
483
- q(1, "open-app", { app: "Kings Foil" }); await wait(); q(2, "kings-foil__search", { query: "x" }); await wait();
484
- assert(tabs === 0 && JSON.parse(got(1).content[0].text).data_tools, "views mean no browser");
485
- assert(JSON.parse(got(2).content[0].text).via === "views", "data tools answer from the views");
486
- q(3, "open-app", { app: "kings-foil", page: true }); await wait();
487
- const names = JSON.parse(got(3).content[0].text).tools.map((t) => t.name);
488
- assert(tabs === 1 && names.includes("search") && names.includes("greet") && names.includes("page-greet"), `page: true adds page tools, a clash renamed: ${names}`);
489
- q(4, "kings-foil__page-greet", { who: "p" }); q(5, "kings-foil__greet", {}); await wait();
490
- assert(JSON.parse(got(4).content[0].text).ev === "ev" && JSON.parse(got(5).content[0].text).via === "views", "each name reaches its own side");
491
- }
492
- console.log("mcp.js self-check ok — one server, apps opened on demand, data tools without a browser, page tools on request");
311
+ // A private app: a paid tool answers with PaymentRequired; with a wallet this server pays the
312
+ // call (under FANGORN_MCP_MAX_PRICE), or buys a pass when the card sells one under FANGORN_MCP_MAX_PASS.
313
+ const { generatePrivateKey } = await import("viem/accounts");
314
+ const req = { scheme: "exact", network: "eip155:84532", amount: "10000", asset: `0x${"aa".repeat(20)}`, payTo: `0x${"5e".repeat(20)}`,
315
+ maxTimeoutSeconds: 120, extra: { name: "USDC", version: "2" } };
316
+ const asked = { x402Version: 2, error: "paid", resource: { url: "https://p.test/mcp" }, accepts: [req] };
317
+ const seen = [];
318
+ const paidServer = async (url, init) => {
319
+ if (url === "https://p.test/pass") {
320
+ if (!init.headers?.["PAYMENT-SIGNATURE"]) return new Response("{}", { status: 402, headers: { "PAYMENT-REQUIRED": btoa(JSON.stringify({ ...asked, accepts: [{ ...req, amount: "2000000" }] })) } });
321
+ return new Response(JSON.stringify({ token: "pass.tok", expires: 9e9 }));
322
+ }
323
+ const m = JSON.parse(init.body);
324
+ const paid = m.params?._meta?.["x402/payment"], pass = init.headers.authorization === "Bearer pass.tok";
325
+ if (m.method === "tools/call") seen.push(pass ? "pass" : paid ? `paid ${paid.accepted.amount}` : "asked");
326
+ const result = m.method === "tools/list" ? { tools: [{ name: "search" }] } : m.method !== "tools/call" ? {}
327
+ : paid || pass ? text({ hits: [1] }) : { isError: true, structuredContent: asked, content: [{ type: "text", text: JSON.stringify(asked) }] };
328
+ return new Response(JSON.stringify({ jsonrpc: "2.0", id: m.id, result }), { headers: { "content-type": "application/json" } });
329
+ };
330
+ const broke = await remoteTools("https://p.test/mcp", paidServer, { wallet: undefined });
331
+ if (!(await broke.call("search", {})).content.at(-1).text.includes("no wallet")) throw new Error("no wallet: the price goes back to the agent");
332
+ const access = { pass_url: "https://p.test/pass", pass: "2000000", call: "10000", decimals: 6 };
333
+ const perCall = await remoteTools("https://p.test/mcp", paidServer, { access, wallet: generatePrivateKey(), maxCall: "0.05" });
334
+ if (JSON.parse((await perCall.call("search", {})).content[0].text).hits[0] !== 1) throw new Error("a paid call");
335
+ const passer = await remoteTools("https://p.test/mcp", paidServer, { access, wallet: generatePrivateKey(), maxPass: "5" });
336
+ await passer.call("search", {}); await passer.call("search", {});
337
+ if (seen.join() !== "asked,asked,paid 10000,asked,pass,pass") throw new Error(`payments: ${seen}`);
338
+ console.log("mcp.js self-check ok — one server, apps opened on demand, calls relayed to each app's own MCP server; a private app's tools paid per call or with a pass bought once, and with no wallet the price is handed back");
493
339
  process.exit(0);
494
340
  }
495
341
 
@@ -499,22 +345,16 @@ globalThis.fetch = cachingFetch();
499
345
  // host with no working IPv6, every attempt times out and fetch fails outright.
500
346
  net.setDefaultAutoSelectFamilyAttemptTimeout?.(2000);
501
347
  const vt = await import("./view-tools.js");
502
- const stale = staleFetch(globalThis.fetch);
503
348
  const fb = argv.indexOf("--from-block");
504
- const fromBlock = fb >= 0 ? BigInt(argv[fb + 1]) : DEFAULT_FROM_BLOCK;
505
- const headed = argv.includes("--headed");
506
- const ci = argv.indexOf("--cdp");
507
- const cdp = ci >= 0 ? argv[ci + 1] : process.env.FANGORN_MCP_CDP || undefined;
349
+ // The SDK's deployment by default: pass --from-block for another one.
350
+ const fromBlock = fb >= 0 ? BigInt(argv[fb + 1]) : (await network()).appRegistryFromBlock;
508
351
  let found, foundAt = 0, explored, exploredAt = 0;
509
352
  const deps = {
510
353
  // ponytail: cached for a minute. The scan is a few RPC calls plus a fetch per card.
511
354
  findApps: async () => {
512
355
  if (!found || Date.now() - foundAt > 60_000) {
513
356
  const { apps, rejected } = await listApps(await fangorn(), { fromBlock });
514
- found = { rejected, apps: await Promise.all(apps.map(async (a) => {
515
- const card = await (await fetch(a.card)).json().catch(() => ({}));
516
- return { ...a, tools: card.skills?.filter((s) => s.tags?.includes("webmcp")).map((s) => s.id) ?? [] };
517
- })) };
357
+ found = { apps, rejected };
518
358
  foundAt = Date.now();
519
359
  }
520
360
  return found;
@@ -522,8 +362,8 @@ const deps = {
522
362
  // ponytail: cached for a minute, like findApps. Two getLogs, a card and catalog per app.
523
363
  exploreApps: async (query) => {
524
364
  if (!explored || Date.now() - exploredAt > 60_000) {
525
- const [ex, { createPublicClient, http }, { arbitrumSepolia }] = await Promise.all([import("../discover/explore.js"), import("viem"), import("viem/chains")]);
526
- explored = { ex, dir: await ex.readDirectory(createPublicClient({ chain: arbitrumSepolia, transport: http() })) };
365
+ const [ex, { createPublicClient, http }, net] = await Promise.all([import("../discover/explore.js"), import("viem"), network()]);
366
+ explored = { ex, dir: await ex.readDirectory(createPublicClient({ chain: net.chain, transport: http(net.rpcUrl) }), { chain: ex.chainOf(net) }) };
527
367
  exploredAt = Date.now();
528
368
  }
529
369
  const { ex, dir } = explored;
@@ -542,13 +382,7 @@ const deps = {
542
382
  return null;
543
383
  },
544
384
  resolveCard,
545
- viewTools: (app) => {
546
- const v = vt.viewTools(app, { fetchCatalog: stale });
547
- if (v) vt.warm({ cacheDir: `${CACHE}/models` }); // already started at initialize; this is the fallback
548
- return v;
549
- },
550
- openTab: (page) => openTab(page, { headed, cdp }),
551
- tabTools, tabCall,
385
+ remoteTools: (url, opts) => remoteTools(url, fetch, opts),
552
386
  };
553
387
  const h = handlers(deps);
554
388
  // The client starts this server with the session, long before an agent opens an
@@ -565,4 +399,4 @@ h.initialize = async (p) => {
565
399
  return reply(p);
566
400
  };
567
401
  deps.notify = serve(h);
568
- log(`ready: apps from block ${fromBlock}; browser ${cdp ?? "local Chrome"}, connected on the first open-app`);
402
+ log(`ready: apps from block ${fromBlock}`);