@hyperweb/telescope 1.15.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 (382) hide show
  1. package/README.md +1529 -0
  2. package/main/build.js +183 -0
  3. package/main/builder.js +229 -0
  4. package/main/bundle.js +162 -0
  5. package/main/bundler.js +100 -0
  6. package/main/cli.js +71 -0
  7. package/main/cmds.js +28 -0
  8. package/main/commands/download.js +122 -0
  9. package/main/commands/generate.js +151 -0
  10. package/main/commands/install.js +143 -0
  11. package/main/commands/transpile.js +197 -0
  12. package/main/contracts/generate.js +31 -0
  13. package/main/contracts/install.js +107 -0
  14. package/main/contracts/message-composer.js +31 -0
  15. package/main/contracts/react-query.js +31 -0
  16. package/main/contracts/recoil.js +31 -0
  17. package/main/file.js +20 -0
  18. package/main/generators/create-aggregated-lcd-client.js +87 -0
  19. package/main/generators/create-all-stargate-clients.js +96 -0
  20. package/main/generators/create-amino-converters.js +43 -0
  21. package/main/generators/create-bundle.js +83 -0
  22. package/main/generators/create-cosmwasm-bundle.js +15 -0
  23. package/main/generators/create-custom-stargate-clients.js +100 -0
  24. package/main/generators/create-helpers.js +119 -0
  25. package/main/generators/create-index.js +75 -0
  26. package/main/generators/create-lcd-client-all.js +116 -0
  27. package/main/generators/create-lcd-client-scoped.js +89 -0
  28. package/main/generators/create-lcd-clients.js +78 -0
  29. package/main/generators/create-mcp-server.js +1853 -0
  30. package/main/generators/create-mobx-bundle.js +52 -0
  31. package/main/generators/create-msg-funcs.js +132 -0
  32. package/main/generators/create-pinia-store-bundle.js +50 -0
  33. package/main/generators/create-pinia-store.js +90 -0
  34. package/main/generators/create-query-funcs.js +133 -0
  35. package/main/generators/create-react-query-bundle.js +103 -0
  36. package/main/generators/create-registries.js +49 -0
  37. package/main/generators/create-root-readme.js +259 -0
  38. package/main/generators/create-rpc-msg-client-all.js +135 -0
  39. package/main/generators/create-rpc-msg-client-scoped.js +114 -0
  40. package/main/generators/create-rpc-msg-clients.js +116 -0
  41. package/main/generators/create-rpc-ops-bundle.js +119 -0
  42. package/main/generators/create-rpc-query-client-all.js +137 -0
  43. package/main/generators/create-rpc-query-client-scoped.js +110 -0
  44. package/main/generators/create-rpc-query-clients.js +198 -0
  45. package/main/generators/create-sdk-module-stargate-clients.js +95 -0
  46. package/main/generators/create-stargate-clients.js +96 -0
  47. package/main/generators/create-types.js +164 -0
  48. package/main/generators/customize-utils.js +50 -0
  49. package/main/helpers/__test__/internalTimestamp.js +49 -0
  50. package/main/helpers/__test__/internalTimestampBigint.js +45 -0
  51. package/main/helpers/binary-coder.js +535 -0
  52. package/main/helpers/decimals.js +111 -0
  53. package/main/helpers/external-comet.js +52 -0
  54. package/main/helpers/external-icjs.js +36 -0
  55. package/main/helpers/external.js +31 -0
  56. package/main/helpers/grpc-gateway.js +348 -0
  57. package/main/helpers/grpc-web.js +14 -0
  58. package/main/helpers/helper-func-types-interface.js +106 -0
  59. package/main/helpers/helper-func-types.js +93 -0
  60. package/main/helpers/index.js +38 -0
  61. package/main/helpers/internal-for-bigint.js +259 -0
  62. package/main/helpers/internal.js +240 -0
  63. package/main/helpers/json-safe.js +12 -0
  64. package/main/helpers/mobx.js +80 -0
  65. package/main/helpers/pinia-endpoint.js +20 -0
  66. package/main/helpers/react-query-hooks-icjs.js +223 -0
  67. package/main/helpers/react-query-hooks.js +258 -0
  68. package/main/helpers/react-query.js +93 -0
  69. package/main/helpers/registry-helper.js +229 -0
  70. package/main/helpers/types-helper.js +165 -0
  71. package/main/helpers/utf8-helper.js +146 -0
  72. package/main/helpers/varint.js +486 -0
  73. package/main/helpers/vue-query-hooks.js +226 -0
  74. package/main/imports.js +416 -0
  75. package/main/index.js +24 -0
  76. package/main/parse.js +194 -0
  77. package/main/prompt.js +64 -0
  78. package/main/protod/bufbuild.js +87 -0
  79. package/main/protod/config.js +30 -0
  80. package/main/protod/git-repo.js +58 -0
  81. package/main/protod/index.js +17 -0
  82. package/main/protod/recursive.js +134 -0
  83. package/main/protod/types.js +2 -0
  84. package/main/protod/utils.js +91 -0
  85. package/main/telescope.js +10 -0
  86. package/main/types.js +2 -0
  87. package/main/utils/common-create-bundle.js +29 -0
  88. package/main/utils/contracts.js +39 -0
  89. package/main/utils/files.js +138 -0
  90. package/main/utils/index.js +163 -0
  91. package/main/utils/unused.js +73 -0
  92. package/module/build.js +176 -0
  93. package/module/builder.js +222 -0
  94. package/module/bundle.js +128 -0
  95. package/module/bundler.js +96 -0
  96. package/module/cli.js +44 -0
  97. package/module/cmds.js +22 -0
  98. package/module/commands/download.js +94 -0
  99. package/module/commands/generate.js +123 -0
  100. package/module/commands/install.js +141 -0
  101. package/module/commands/transpile.js +169 -0
  102. package/module/contracts/generate.js +29 -0
  103. package/module/contracts/install.js +105 -0
  104. package/module/contracts/message-composer.js +29 -0
  105. package/module/contracts/react-query.js +29 -0
  106. package/module/contracts/recoil.js +29 -0
  107. package/module/file.js +18 -0
  108. package/module/generators/create-aggregated-lcd-client.js +83 -0
  109. package/module/generators/create-all-stargate-clients.js +92 -0
  110. package/module/generators/create-amino-converters.js +39 -0
  111. package/module/generators/create-bundle.js +79 -0
  112. package/module/generators/create-cosmwasm-bundle.js +11 -0
  113. package/module/generators/create-custom-stargate-clients.js +96 -0
  114. package/module/generators/create-helpers.js +112 -0
  115. package/module/generators/create-index.js +45 -0
  116. package/module/generators/create-lcd-client-all.js +89 -0
  117. package/module/generators/create-lcd-client-scoped.js +62 -0
  118. package/module/generators/create-lcd-clients.js +74 -0
  119. package/module/generators/create-mcp-server.js +1849 -0
  120. package/module/generators/create-mobx-bundle.js +25 -0
  121. package/module/generators/create-msg-funcs.js +128 -0
  122. package/module/generators/create-pinia-store-bundle.js +23 -0
  123. package/module/generators/create-pinia-store.js +86 -0
  124. package/module/generators/create-query-funcs.js +129 -0
  125. package/module/generators/create-react-query-bundle.js +76 -0
  126. package/module/generators/create-registries.js +45 -0
  127. package/module/generators/create-root-readme.js +255 -0
  128. package/module/generators/create-rpc-msg-client-all.js +108 -0
  129. package/module/generators/create-rpc-msg-client-scoped.js +87 -0
  130. package/module/generators/create-rpc-msg-clients.js +112 -0
  131. package/module/generators/create-rpc-ops-bundle.js +92 -0
  132. package/module/generators/create-rpc-query-client-all.js +110 -0
  133. package/module/generators/create-rpc-query-client-scoped.js +83 -0
  134. package/module/generators/create-rpc-query-clients.js +198 -0
  135. package/module/generators/create-sdk-module-stargate-clients.js +91 -0
  136. package/module/generators/create-stargate-clients.js +92 -0
  137. package/module/generators/create-types.js +137 -0
  138. package/module/generators/customize-utils.js +46 -0
  139. package/module/helpers/__test__/internalTimestamp.js +39 -0
  140. package/module/helpers/__test__/internalTimestampBigint.js +38 -0
  141. package/module/helpers/binary-coder.js +531 -0
  142. package/module/helpers/decimals.js +108 -0
  143. package/module/helpers/external-comet.js +49 -0
  144. package/module/helpers/external-icjs.js +33 -0
  145. package/module/helpers/external.js +28 -0
  146. package/module/helpers/grpc-gateway.js +345 -0
  147. package/module/helpers/grpc-web.js +11 -0
  148. package/module/helpers/helper-func-types-interface.js +102 -0
  149. package/module/helpers/helper-func-types.js +89 -0
  150. package/module/helpers/index.js +22 -0
  151. package/module/helpers/internal-for-bigint.js +255 -0
  152. package/module/helpers/internal.js +236 -0
  153. package/module/helpers/json-safe.js +9 -0
  154. package/module/helpers/mobx.js +77 -0
  155. package/module/helpers/pinia-endpoint.js +17 -0
  156. package/module/helpers/react-query-hooks-icjs.js +219 -0
  157. package/module/helpers/react-query-hooks.js +254 -0
  158. package/module/helpers/react-query.js +89 -0
  159. package/module/helpers/registry-helper.js +225 -0
  160. package/module/helpers/types-helper.js +161 -0
  161. package/module/helpers/utf8-helper.js +143 -0
  162. package/module/helpers/varint.js +483 -0
  163. package/module/helpers/vue-query-hooks.js +222 -0
  164. package/module/imports.js +382 -0
  165. package/module/index.js +8 -0
  166. package/module/parse.js +185 -0
  167. package/module/prompt.js +58 -0
  168. package/module/protod/bufbuild.js +76 -0
  169. package/module/protod/config.js +27 -0
  170. package/module/protod/git-repo.js +54 -0
  171. package/module/protod/index.js +1 -0
  172. package/module/protod/recursive.js +125 -0
  173. package/module/protod/types.js +1 -0
  174. package/module/protod/utils.js +77 -0
  175. package/module/telescope.js +8 -0
  176. package/module/types.js +1 -0
  177. package/module/utils/common-create-bundle.js +25 -0
  178. package/module/utils/contracts.js +33 -0
  179. package/module/utils/files.js +106 -0
  180. package/module/utils/index.js +143 -0
  181. package/module/utils/unused.js +47 -0
  182. package/package.json +115 -0
  183. package/src/build.ts +255 -0
  184. package/src/builder.ts +302 -0
  185. package/src/bundle.ts +160 -0
  186. package/src/bundler.ts +153 -0
  187. package/src/cli.js +51 -0
  188. package/src/cmds.js +25 -0
  189. package/src/commands/download.ts +120 -0
  190. package/src/commands/generate.ts +156 -0
  191. package/src/commands/install.ts +154 -0
  192. package/src/commands/transpile.ts +198 -0
  193. package/src/contracts/generate.ts +33 -0
  194. package/src/contracts/install.ts +118 -0
  195. package/src/contracts/message-composer.ts +34 -0
  196. package/src/contracts/react-query.ts +33 -0
  197. package/src/contracts/recoil.ts +32 -0
  198. package/src/file.js +20 -0
  199. package/src/generators/create-aggregated-lcd-client.ts +133 -0
  200. package/src/generators/create-all-stargate-clients.ts +121 -0
  201. package/src/generators/create-amino-converters.ts +62 -0
  202. package/src/generators/create-bundle.ts +97 -0
  203. package/src/generators/create-cosmwasm-bundle.ts +17 -0
  204. package/src/generators/create-custom-stargate-clients.ts +128 -0
  205. package/src/generators/create-helpers.ts +196 -0
  206. package/src/generators/create-index.ts +72 -0
  207. package/src/generators/create-lcd-client-all.ts +139 -0
  208. package/src/generators/create-lcd-client-scoped.ts +109 -0
  209. package/src/generators/create-lcd-clients.ts +108 -0
  210. package/src/generators/create-mcp-server.ts +1902 -0
  211. package/src/generators/create-mobx-bundle.ts +31 -0
  212. package/src/generators/create-msg-funcs.ts +219 -0
  213. package/src/generators/create-pinia-store-bundle.ts +35 -0
  214. package/src/generators/create-pinia-store.ts +121 -0
  215. package/src/generators/create-query-funcs.ts +224 -0
  216. package/src/generators/create-react-query-bundle.ts +111 -0
  217. package/src/generators/create-registries.ts +70 -0
  218. package/src/generators/create-root-readme.ts +316 -0
  219. package/src/generators/create-rpc-msg-client-all.ts +167 -0
  220. package/src/generators/create-rpc-msg-client-scoped.ts +147 -0
  221. package/src/generators/create-rpc-msg-clients.ts +165 -0
  222. package/src/generators/create-rpc-ops-bundle.ts +155 -0
  223. package/src/generators/create-rpc-query-client-all.ts +173 -0
  224. package/src/generators/create-rpc-query-client-scoped.ts +142 -0
  225. package/src/generators/create-rpc-query-clients.ts +304 -0
  226. package/src/generators/create-sdk-module-stargate-clients.ts +120 -0
  227. package/src/generators/create-stargate-clients.ts +123 -0
  228. package/src/generators/create-types.ts +236 -0
  229. package/src/generators/customize-utils.ts +54 -0
  230. package/src/helpers/__test__/internalTimestamp.test.ts +79 -0
  231. package/src/helpers/__test__/internalTimestamp.ts +58 -0
  232. package/src/helpers/__test__/internalTimestampBigint.test.ts +78 -0
  233. package/src/helpers/__test__/internalTimestampBigint.ts +58 -0
  234. package/src/helpers/binary-coder.ts +533 -0
  235. package/src/helpers/decimals.ts +108 -0
  236. package/src/helpers/external-comet.ts +49 -0
  237. package/src/helpers/external-icjs.ts +33 -0
  238. package/src/helpers/external.ts +28 -0
  239. package/src/helpers/grpc-gateway.ts +345 -0
  240. package/src/helpers/grpc-web.ts +11 -0
  241. package/src/helpers/helper-func-types-interface.ts +104 -0
  242. package/src/helpers/helper-func-types.ts +91 -0
  243. package/src/helpers/index.ts +22 -0
  244. package/src/helpers/internal-for-bigint.ts +257 -0
  245. package/src/helpers/internal.ts +238 -0
  246. package/src/helpers/json-safe.ts +11 -0
  247. package/src/helpers/mobx.ts +77 -0
  248. package/src/helpers/pinia-endpoint.ts +17 -0
  249. package/src/helpers/react-query-hooks-icjs.ts +223 -0
  250. package/src/helpers/react-query-hooks.ts +266 -0
  251. package/src/helpers/react-query.ts +101 -0
  252. package/src/helpers/registry-helper.ts +227 -0
  253. package/src/helpers/types-helper.ts +169 -0
  254. package/src/helpers/utf8-helper.ts +143 -0
  255. package/src/helpers/varint.ts +483 -0
  256. package/src/helpers/vue-query-hooks.ts +224 -0
  257. package/src/imports.ts +499 -0
  258. package/src/index.ts +12 -0
  259. package/src/parse.ts +243 -0
  260. package/src/prompt.js +65 -0
  261. package/src/protod/bufbuild.spec.ts +80 -0
  262. package/src/protod/bufbuild.ts +95 -0
  263. package/src/protod/config.ts +30 -0
  264. package/src/protod/git-repo.ts +74 -0
  265. package/src/protod/index.ts +1 -0
  266. package/src/protod/recursive.spec.ts +164 -0
  267. package/src/protod/recursive.ts +180 -0
  268. package/src/protod/test-data/.protod.config.json +42 -0
  269. package/src/protod/test-data/buf.lock +23 -0
  270. package/src/protod/test-data/buf.yaml +25 -0
  271. package/src/protod/test-data/buf2.yaml +20 -0
  272. package/src/protod/test-data/cosmos/buf.lock +23 -0
  273. package/src/protod/test-data/cosmos/crypto/secp256k1/keys.proto +38 -0
  274. package/src/protod/test-data/model.proto +101 -0
  275. package/src/protod/types.ts +55 -0
  276. package/src/protod/utils.spec.ts +68 -0
  277. package/src/protod/utils.ts +90 -0
  278. package/src/telescope.js +9 -0
  279. package/src/types.ts +46 -0
  280. package/src/utils/common-create-bundle.ts +62 -0
  281. package/src/utils/contracts.ts +37 -0
  282. package/src/utils/files.ts +145 -0
  283. package/src/utils/index.ts +150 -0
  284. package/src/utils/unused.ts +52 -0
  285. package/types/build.d.ts +41 -0
  286. package/types/builder.d.ts +50 -0
  287. package/types/bundle.d.ts +30 -0
  288. package/types/bundler.d.ts +31 -0
  289. package/types/cli.d.ts +1 -0
  290. package/types/cmds.d.ts +11 -0
  291. package/types/commands/download.d.ts +5 -0
  292. package/types/commands/generate.d.ts +2 -0
  293. package/types/commands/install.d.ts +2 -0
  294. package/types/commands/transpile.d.ts +4 -0
  295. package/types/contracts/generate.d.ts +2 -0
  296. package/types/contracts/install.d.ts +2 -0
  297. package/types/contracts/message-composer.d.ts +2 -0
  298. package/types/contracts/react-query.d.ts +2 -0
  299. package/types/contracts/recoil.d.ts +2 -0
  300. package/types/file.d.ts +2 -0
  301. package/types/generators/create-aggregated-lcd-client.d.ts +2 -0
  302. package/types/generators/create-all-stargate-clients.d.ts +3 -0
  303. package/types/generators/create-amino-converters.d.ts +3 -0
  304. package/types/generators/create-bundle.d.ts +3 -0
  305. package/types/generators/create-combined-stargate-clients.d.ts +3 -0
  306. package/types/generators/create-cosmwasm-bundle.d.ts +2 -0
  307. package/types/generators/create-custom-stargate-clients.d.ts +3 -0
  308. package/types/generators/create-helpers.d.ts +2 -0
  309. package/types/generators/create-index.d.ts +2 -0
  310. package/types/generators/create-lcd-client-all.d.ts +3 -0
  311. package/types/generators/create-lcd-client-scoped.d.ts +3 -0
  312. package/types/generators/create-lcd-clients.d.ts +3 -0
  313. package/types/generators/create-mcp-server.d.ts +3 -0
  314. package/types/generators/create-mobx-bundle.d.ts +2 -0
  315. package/types/generators/create-msg-funcs.d.ts +3 -0
  316. package/types/generators/create-pinia-store-bundle.d.ts +2 -0
  317. package/types/generators/create-pinia-store.d.ts +3 -0
  318. package/types/generators/create-query-funcs.d.ts +3 -0
  319. package/types/generators/create-react-query-bundle.d.ts +2 -0
  320. package/types/generators/create-registries.d.ts +3 -0
  321. package/types/generators/create-root-readme.d.ts +2 -0
  322. package/types/generators/create-rpc-msg-client-all.d.ts +3 -0
  323. package/types/generators/create-rpc-msg-client-scoped.d.ts +3 -0
  324. package/types/generators/create-rpc-msg-clients.d.ts +3 -0
  325. package/types/generators/create-rpc-ops-bundle.d.ts +2 -0
  326. package/types/generators/create-rpc-query-client-all.d.ts +3 -0
  327. package/types/generators/create-rpc-query-client-scoped.d.ts +3 -0
  328. package/types/generators/create-rpc-query-clients.d.ts +3 -0
  329. package/types/generators/create-scoped-stargate-clients.d.ts +3 -0
  330. package/types/generators/create-sdk-module-stargate-clients.d.ts +3 -0
  331. package/types/generators/create-stargate-clients.d.ts +3 -0
  332. package/types/generators/create-types.d.ts +3 -0
  333. package/types/generators/create-unified-stargate-clients.d.ts +3 -0
  334. package/types/generators/customize-utils.d.ts +2 -0
  335. package/types/helpers/__test__/internalTimestamp.d.ts +21 -0
  336. package/types/helpers/__test__/internalTimestampBigint.d.ts +20 -0
  337. package/types/helpers/binary-coder.d.ts +2 -0
  338. package/types/helpers/decimals.d.ts +1 -0
  339. package/types/helpers/external-comet.d.ts +1 -0
  340. package/types/helpers/external-icjs.d.ts +1 -0
  341. package/types/helpers/external.d.ts +1 -0
  342. package/types/helpers/generated-type.d.ts +1 -0
  343. package/types/helpers/grpc-gateway.d.ts +1 -0
  344. package/types/helpers/grpc-web.d.ts +1 -0
  345. package/types/helpers/helper-func-types-interface.d.ts +2 -0
  346. package/types/helpers/helper-func-types.d.ts +2 -0
  347. package/types/helpers/index.d.ts +22 -0
  348. package/types/helpers/internal-for-bigint.d.ts +2 -0
  349. package/types/helpers/internal.d.ts +2 -0
  350. package/types/helpers/internalForBigInt.d.ts +1 -0
  351. package/types/helpers/json-safe.d.ts +1 -0
  352. package/types/helpers/mobx.d.ts +1 -0
  353. package/types/helpers/pinia-endpoint.d.ts +1 -0
  354. package/types/helpers/react-query-hooks-icjs.d.ts +2 -0
  355. package/types/helpers/react-query-hooks.d.ts +2 -0
  356. package/types/helpers/react-query.d.ts +2 -0
  357. package/types/helpers/registry-helper.d.ts +2 -0
  358. package/types/helpers/types-helper.d.ts +2 -0
  359. package/types/helpers/types.d.ts +1 -0
  360. package/types/helpers/utf8-helper.d.ts +1 -0
  361. package/types/helpers/varint.d.ts +1 -0
  362. package/types/helpers/vue-query-hooks.d.ts +2 -0
  363. package/types/helpers/vue-query.d.ts +2 -0
  364. package/types/imports.d.ts +17 -0
  365. package/types/index.d.ts +6 -0
  366. package/types/parse.d.ts +15 -0
  367. package/types/prompt.d.ts +3 -0
  368. package/types/protod/bufbuild.d.ts +6 -0
  369. package/types/protod/config.d.ts +7 -0
  370. package/types/protod/git-repo.d.ts +11 -0
  371. package/types/protod/index.d.ts +1 -0
  372. package/types/protod/proto-download.d.ts +2 -0
  373. package/types/protod/recursive.d.ts +4 -0
  374. package/types/protod/types.d.ts +49 -0
  375. package/types/protod/utils.d.ts +11 -0
  376. package/types/telescope.d.ts +2 -0
  377. package/types/types.d.ts +43 -0
  378. package/types/utils/common-create-bundle.d.ts +18 -0
  379. package/types/utils/contracts.d.ts +6 -0
  380. package/types/utils/files.d.ts +5 -0
  381. package/types/utils/index.d.ts +16 -0
  382. package/types/utils/unused.d.ts +5 -0
@@ -0,0 +1,1849 @@
1
+ import { writeFileSync, mkdirSync, cpSync, existsSync } from 'fs';
2
+ import { join, dirname, basename } from 'path';
3
+ export const plugin = (builder, bundler) => {
4
+ // Early return if MCP server is not enabled
5
+ if (!builder.options.mcpServer?.enabled) {
6
+ return;
7
+ }
8
+ // Use the output directory name instead of bundle base
9
+ const outputDirName = basename(builder.outPath);
10
+ const packageName = outputDirName || bundler.bundle.base;
11
+ const parentDir = dirname(builder.outPath);
12
+ const mcpServerPath = join(parentDir, `${packageName}-mcp`);
13
+ // Ensure MCP server directory exists
14
+ mkdirSync(mcpServerPath, { recursive: true });
15
+ mkdirSync(join(mcpServerPath, 'src'), { recursive: true });
16
+ mkdirSync(join(mcpServerPath, 'src', 'prompts'), { recursive: true });
17
+ mkdirSync(join(mcpServerPath, 'src', 'telescope-examples'), { recursive: true });
18
+ // Generate package.json for MCP server
19
+ const packageJson = generateMcpPackageJson(packageName);
20
+ writeFileSync(join(mcpServerPath, 'package.json'), JSON.stringify(packageJson, null, 2));
21
+ // Generate main MCP server file
22
+ const indexContent = `#!/usr/bin/env node
23
+
24
+ import { readFileSync } from 'node:fs';
25
+ import { dirname, resolve } from 'node:path';
26
+ import { fileURLToPath } from 'node:url';
27
+
28
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
29
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
30
+ import { z } from 'zod';
31
+
32
+ // Get package.json version
33
+ const __filename = fileURLToPath(import.meta.url);
34
+ const __dirname = dirname(__filename);
35
+ const packageJson = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf8'));
36
+ const VERSION = packageJson.version;
37
+
38
+ async function main() {
39
+ const server = new McpServer({
40
+ name: '${packageName} MCP Server',
41
+ version: VERSION,
42
+ });
43
+
44
+ // Add prompts for AI agents
45
+ server.prompt(
46
+ 'codegen-usage',
47
+ 'Guide for using telescope generated code',
48
+ async () => {
49
+ const promptPath = resolve(__dirname, 'prompts/codegen-usage.md');
50
+ const content = readFileSync(promptPath, 'utf-8');
51
+ return {
52
+ messages: [{
53
+ role: 'user',
54
+ content: {
55
+ type: 'text',
56
+ text: content
57
+ }
58
+ }]
59
+ };
60
+ }
61
+ );
62
+
63
+ server.prompt(
64
+ 'agent-guidelines',
65
+ 'Guidelines for MCP agents using ${packageName}',
66
+ async () => {
67
+ const promptPath = resolve(__dirname, 'prompts/agent-guidelines.md');
68
+ const content = readFileSync(promptPath, 'utf-8');
69
+ return {
70
+ messages: [{
71
+ role: 'user',
72
+ content: {
73
+ type: 'text',
74
+ text: content
75
+ }
76
+ }]
77
+ };
78
+ }
79
+ );
80
+
81
+ // Register blockchain function generator tool
82
+ server.tool(
83
+ 'create-blockchain-function',
84
+ 'Create custom blockchain functions by referencing telescope examples and generated code',
85
+ {
86
+ task: z.string().describe('The blockchain task to implement (e.g., "get balance", "check staking rewards", "query validators")').optional(),
87
+ chainName: z.string().describe('The blockchain name (e.g., cosmos, osmosis, injective)').optional(),
88
+ functionType: z.enum(['query', 'transaction', 'react-hook', 'utility']).describe('Type of function to create').optional(),
89
+ customRequirements: z.string().describe('Any specific requirements or modifications needed').optional()
90
+ },
91
+ async (args) => {
92
+ try {
93
+ const { task = 'get account balance', chainName = 'cosmos', functionType = 'query', customRequirements } = args;
94
+
95
+ // Read available examples
96
+ const examplesPath = resolve(__dirname, 'telescope-examples');
97
+ let availableExamples: string[] = [];
98
+
99
+ try {
100
+ const fs = await import('fs');
101
+ availableExamples = fs.readdirSync(examplesPath)
102
+ .filter(file => file.endsWith('.ts'))
103
+ .map(file => file.replace('.ts', ''));
104
+ } catch (error) {
105
+ // If examples directory doesn't exist, provide default list
106
+ availableExamples = [
107
+ 'config-example', 'useBalance', 'useBalanceFunc', 'getBalance',
108
+ 'useAssets', 'useStakingData', 'useValidators', 'useVoting',
109
+ 'useVotingData', 'useContractInfo', 'useQueryContract',
110
+ 'useCodeDetails', 'useMyContracts', 'useGrants', 'useSendData',
111
+ 'useTotalAssets', 'useBalanceReact'
112
+ ];
113
+ }
114
+
115
+ const examplesList = availableExamples.map(example => \`- **\${example}.ts**: Reference implementation\`).join('\\n');
116
+
117
+ const relevantExamples = getRelevantExamples(task, availableExamples)
118
+ .map(example => \`- **\${example}**: \${getExampleDescription(example)}\`)
119
+ .join('\\n');
120
+
121
+ const codeBlockStart = '\`\`\`';
122
+ const codeBlockEnd = '\`\`\`';
123
+
124
+ const response = [
125
+ '# Blockchain Function Generator',
126
+ '',
127
+ \`## Task: \${task}\`,
128
+ \`## Chain: \${chainName}\`,
129
+ \`## Function Type: \${functionType}\`,
130
+ customRequirements ? \`## Custom Requirements: \${customRequirements}\` : '',
131
+ '',
132
+ '## Instructions for Implementation',
133
+ '',
134
+ '### Step 1: Review Available Examples',
135
+ 'The following example files are available in \`src/telescope-examples/\`:',
136
+ '',
137
+ examplesList,
138
+ '',
139
+ '### Step 2: Identify Relevant Examples',
140
+ \`Based on your task "\${task}", you should primarily reference:\`,
141
+ '',
142
+ relevantExamples,
143
+ '',
144
+ '### Step 3: Implementation Pattern',
145
+ '',
146
+ \`**For Query Functions (\${functionType === 'query' ? 'SELECTED' : 'Available'}):**\`,
147
+ \`\${codeBlockStart}typescript\`,
148
+ "import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';",
149
+ '',
150
+ 'export const customQueryFunction = async (params: QueryParams) => {',
151
+ \` const rpcEndpoint = 'https://\${chainName}-rpc.quickapi.com:443';\`,
152
+ ' ',
153
+ ' try {',
154
+ ' const result = await getBalance(rpcEndpoint, params);',
155
+ ' return {',
156
+ ' success: true,',
157
+ ' data: result,',
158
+ ' };',
159
+ ' } catch (error) {',
160
+ ' return {',
161
+ ' success: false,',
162
+ ' error: (error as Error).message,',
163
+ ' };',
164
+ ' }',
165
+ '};',
166
+ codeBlockEnd,
167
+ '',
168
+ \`**For React Hooks (\${functionType === 'react-hook' ? 'SELECTED' : 'Available'}):**\`,
169
+ \`\${codeBlockStart}typescript\`,
170
+ "import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';",
171
+ "import { defaultContext } from '@tanstack/react-query';",
172
+ '',
173
+ 'export const useCustomHook = (params: HookParams) => {',
174
+ \` const rpcEndpoint = 'https://\${chainName}-rpc.quickapi.com:443';\`,
175
+ ' ',
176
+ ' return useGetBalance({',
177
+ ' request: params,',
178
+ ' options: {',
179
+ ' enabled: !!params.address,',
180
+ ' context: defaultContext,',
181
+ ' },',
182
+ ' clientResolver: rpcEndpoint,',
183
+ ' });',
184
+ '};',
185
+ codeBlockEnd,
186
+ '',
187
+ '### Step 4: Configuration Setup',
188
+ 'Always include proper chain configuration. Reference \`config-example.ts\`:',
189
+ '',
190
+ \`\${codeBlockStart}typescript\`,
191
+ 'import { assetLists, chains } from "@chain-registry/v2";',
192
+ '',
193
+ \`export const targetChainName = '\${chainName}';\`,
194
+ \`export const rpcEndpoint = 'https://\${chainName}-rpc.quickapi.com:443';\`,
195
+ 'export const chain = chains.find((chain) => chain.chainName === targetChainName);',
196
+ 'export const assetList = assetLists.find((assetList) => assetList.chainName === targetChainName);',
197
+ codeBlockEnd,
198
+ '',
199
+ '### Step 5: Error Handling & Best Practices',
200
+ '- Always wrap async calls in try-catch blocks',
201
+ '- Validate input parameters before making requests',
202
+ '- Handle network timeouts and connection errors',
203
+ '- Convert base units to human-readable amounts (uatom → ATOM)',
204
+ '- Include proper TypeScript types',
205
+ '',
206
+ '### Step 6: Testing Your Function',
207
+ \`\${codeBlockStart}typescript\`,
208
+ '// Example usage',
209
+ 'const result = await customQueryFunction({',
210
+ " address: 'cosmos1...',",
211
+ " denom: 'uatom'",
212
+ '});',
213
+ '',
214
+ 'if (result.success) {',
215
+ " console.log('Result:', result.data);",
216
+ '} else {',
217
+ " console.error('Error:', result.error);",
218
+ '}',
219
+ codeBlockEnd,
220
+ '',
221
+ '## Additional Resources',
222
+ '',
223
+ '- **Full codebase reference**: \`src/telescope/\` directory contains all generated types and functions',
224
+ '- **Configuration examples**: \`src/telescope-examples/config-example.ts\`',
225
+ '- **Chain registry data**: \`src/prompts/chains.json\`',
226
+ '- **Usage guidelines**: Use the \`codegen-usage\` and \`agent-guidelines\` prompts for detailed instructions',
227
+ '',
228
+ '## Next Steps',
229
+ '',
230
+ '1. Review the suggested example files above',
231
+ '2. Copy and modify the relevant pattern for your use case',
232
+ '3. Test your implementation with proper error handling',
233
+ '4. Ensure proper TypeScript types are used',
234
+ '',
235
+ 'The examples in \`telescope-examples/\` are production-ready patterns that you can adapt for any blockchain task.'
236
+ ].filter(line => line !== '').join('\\n');
237
+
238
+ return {
239
+ content: [{
240
+ type: "text",
241
+ text: response
242
+ }]
243
+ };
244
+
245
+ } catch (error) {
246
+ return {
247
+ content: [{
248
+ type: "text",
249
+ text: \`Error generating blockchain function guidance: \${(error as Error).message}\`
250
+ }]
251
+ };
252
+ }
253
+ }
254
+ );
255
+
256
+ const transport = new StdioServerTransport();
257
+ await server.connect(transport);
258
+ console.log('${packageName} MCP server started on stdio');
259
+ }
260
+
261
+ // Helper functions for example recommendations
262
+ function getRelevantExamples(task: string, availableExamples: string[]): string[] {
263
+ const taskLower = task.toLowerCase();
264
+ const relevantExamples: string[] = [];
265
+
266
+ // Balance-related tasks
267
+ if (taskLower.includes('balance')) {
268
+ relevantExamples.push('useBalance', 'useBalanceFunc', 'getBalance');
269
+ if (taskLower.includes('react')) {
270
+ relevantExamples.push('useBalanceReact');
271
+ }
272
+ }
273
+
274
+ // Staking-related tasks
275
+ if (taskLower.includes('staking') || taskLower.includes('delegate') || taskLower.includes('validator')) {
276
+ relevantExamples.push('useStakingData', 'useValidators');
277
+ }
278
+
279
+ // Governance/voting tasks
280
+ if (taskLower.includes('voting') || taskLower.includes('proposal') || taskLower.includes('governance')) {
281
+ relevantExamples.push('useVoting', 'useVotingData');
282
+ }
283
+
284
+ // Assets/portfolio tasks
285
+ if (taskLower.includes('asset') || taskLower.includes('portfolio') || taskLower.includes('total')) {
286
+ relevantExamples.push('useAssets', 'useTotalAssets');
287
+ }
288
+
289
+ // Contract-related tasks
290
+ if (taskLower.includes('contract') || taskLower.includes('cosmwasm')) {
291
+ relevantExamples.push('useContractInfo', 'useQueryContract', 'useCodeDetails', 'useMyContracts');
292
+ }
293
+
294
+ // Transaction/sending tasks
295
+ if (taskLower.includes('send') || taskLower.includes('transaction') || taskLower.includes('transfer')) {
296
+ relevantExamples.push('useSendData', 'getBalance');
297
+ }
298
+
299
+ // Authorization tasks
300
+ if (taskLower.includes('grant') || taskLower.includes('authorization') || taskLower.includes('authz')) {
301
+ relevantExamples.push('useGrants');
302
+ }
303
+
304
+ // Always include config as it's fundamental
305
+ relevantExamples.unshift('config-example');
306
+
307
+ // Remove duplicates and ensure examples exist
308
+ return [...new Set(relevantExamples)].filter(example =>
309
+ availableExamples.includes(example)
310
+ );
311
+ }
312
+
313
+ function getExampleDescription(example: string): string {
314
+ const descriptions: Record<string, string> = {
315
+ 'config-example': 'Chain configuration and RPC endpoints setup',
316
+ 'useBalance': 'React hook for querying account balance',
317
+ 'useBalanceFunc': 'Direct function for balance queries',
318
+ 'useBalanceReact': 'React hook with BigNumber for balance queries',
319
+ 'getBalance': 'Basic balance query with transaction examples',
320
+ 'useAssets': 'Query all token balances for an account',
321
+ 'useStakingData': 'Comprehensive staking information (delegations, rewards, validators)',
322
+ 'useValidators': 'Query active validators with sorting',
323
+ 'useVoting': 'Active governance proposals in voting period',
324
+ 'useVotingData': 'All governance proposals with categorization',
325
+ 'useContractInfo': 'Smart contract information queries',
326
+ 'useQueryContract': 'Execute smart contract queries',
327
+ 'useCodeDetails': 'Contract code information and metadata',
328
+ 'useMyContracts': 'Contracts created by specific address',
329
+ 'useGrants': 'Authorization grants (granter/grantee)',
330
+ 'useSendData': 'Prepare transaction data for token transfers',
331
+ 'useTotalAssets': 'Portfolio summary with total asset calculations'
332
+ };
333
+
334
+ return descriptions[example] || 'Blockchain utility function';
335
+ }
336
+
337
+ main().catch((error) => {
338
+ console.error('Fatal error in main()', error);
339
+ process.exit(1);
340
+ });
341
+ `;
342
+ writeFileSync(join(mcpServerPath, 'src', 'index.ts'), indexContent);
343
+ // Generate telescope loader utility
344
+ const telescopeLoaderCode = generateTelescopeLoader(packageName);
345
+ writeFileSync(join(mcpServerPath, 'src', 'telescope-loader.ts'), telescopeLoaderCode);
346
+ // Generate TypeScript configuration
347
+ const tsConfig = generateTsConfig();
348
+ writeFileSync(join(mcpServerPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2));
349
+ // Generate README
350
+ const readme = generateReadme(packageName);
351
+ writeFileSync(join(mcpServerPath, 'README.md'), readme);
352
+ // Generate comprehensive prompts and guidelines
353
+ generateComprehensivePrompts(mcpServerPath, packageName);
354
+ // Generate telescope examples
355
+ generateTelescopeExamples(mcpServerPath, packageName);
356
+ // Copy entire telescope generated codebase for AI reference (excluded from build)
357
+ copyTelescopeCodebase(builder, mcpServerPath, packageName);
358
+ };
359
+ function generateMcpPackageJson(packageName) {
360
+ return {
361
+ name: `@${packageName}/mcp-server`,
362
+ version: "0.1.0",
363
+ description: `MCP server for ${packageName} blockchain interactions`,
364
+ main: "dist/index.js",
365
+ type: "module",
366
+ bin: {
367
+ [`@${packageName}/mcp-server`]: "./dist/index.js"
368
+ },
369
+ scripts: {
370
+ build: "rimraf dist && tsc",
371
+ clean: "rimraf dist",
372
+ test: "vitest",
373
+ inspector: "npm run build && npm exec @modelcontextprotocol/inspector node dist/index.js",
374
+ format: "biome check --write",
375
+ lint: "biome check"
376
+ },
377
+ dependencies: {
378
+ "@modelcontextprotocol/sdk": "^1.7.0",
379
+ "zod": "^3.24.2"
380
+ },
381
+ devDependencies: {
382
+ "@biomejs/biome": "1.9.4",
383
+ "@types/node": "^22.13.10",
384
+ "rimraf": "^6.0.1",
385
+ "typescript": "^5.8.2",
386
+ "vitest": "^3.1.1"
387
+ },
388
+ files: ["dist"],
389
+ publishConfig: {
390
+ access: "public"
391
+ }
392
+ };
393
+ }
394
+ function generateMcpServerCode(builder, bundler) {
395
+ const outputDirName = basename(builder.outPath);
396
+ const packageName = outputDirName || bundler.bundle.base;
397
+ return `#!/usr/bin/env node
398
+
399
+ import { readFileSync } from 'node:fs';
400
+ import { dirname, resolve } from 'node:path';
401
+ import { fileURLToPath } from 'node:url';
402
+
403
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
404
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
405
+ import { z } from 'zod';
406
+
407
+ // NOTE: Tool imports are commented out since they are excluded from build
408
+ // Uncomment and modify these imports if you want to include tools in your build
409
+ /*
410
+ import { getBalanceTool } from './tools/getBalance.js';
411
+ import { getBalanceReactTool } from './tools/useBalance.js';
412
+ */
413
+
414
+ // Get package.json version
415
+ const __filename = fileURLToPath(import.meta.url);
416
+ const __dirname = dirname(__filename);
417
+ const packageJson = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf8'));
418
+ const VERSION = packageJson.version;
419
+
420
+ async function main() {
421
+ const server = new McpServer({
422
+ name: '${packageName} MCP Server',
423
+ version: VERSION,
424
+ });
425
+
426
+ // Add prompts for AI agents
427
+ server.prompt(
428
+ 'codegen-usage',
429
+ 'Guide for using telescope generated code',
430
+ async () => {
431
+ const promptPath = resolve(__dirname, 'prompts/codegen-usage.md');
432
+ const content = readFileSync(promptPath, 'utf-8');
433
+ return {
434
+ messages: [{
435
+ role: 'user',
436
+ content: {
437
+ type: 'text',
438
+ text: content
439
+ }
440
+ }]
441
+ };
442
+ }
443
+ );
444
+
445
+ server.prompt(
446
+ 'agent-guidelines',
447
+ 'Guidelines for MCP agents using ${packageName}',
448
+ async () => {
449
+ const promptPath = resolve(__dirname, 'prompts/agent-guidelines.md');
450
+ const content = readFileSync(promptPath, 'utf-8');
451
+ return {
452
+ messages: [{
453
+ role: 'user',
454
+ content: {
455
+ type: 'text',
456
+ text: content
457
+ }
458
+ }]
459
+ };
460
+ }
461
+ );
462
+
463
+ // NOTE: Tool registrations are commented out since tool functions are not imported
464
+ // Uncomment and modify these registrations if you want to include tools in your build
465
+ /*
466
+ // Register tools
467
+ server.tool('get-balance', 'Get account balance for a specific token', {
468
+ address: z.string().describe('The account address'),
469
+ chainName: z.string().describe('The blockchain name (e.g., cosmos, osmosis)').optional(),
470
+ denom: z.string().describe('The token denomination (e.g., uatom, uosmo)').optional()
471
+ }, getBalanceTool);
472
+
473
+ server.tool('get-balance-react', 'Get balance using React hook pattern', {
474
+ address: z.string().describe('The account address'),
475
+ chainName: z.string().describe('The blockchain name').optional(),
476
+ displayDenom: z.string().describe('The display denomination').optional()
477
+ }, getBalanceReactTool);
478
+ */
479
+
480
+ const transport = new StdioServerTransport();
481
+ await server.connect(transport);
482
+ console.log('${packageName} MCP server started on stdio');
483
+ }
484
+
485
+ main().catch((error) => {
486
+ console.error('Fatal error in main()', error);
487
+ process.exit(1);
488
+ });
489
+ `;
490
+ }
491
+ function generateTsConfig() {
492
+ return {
493
+ compilerOptions: {
494
+ target: "ES2022",
495
+ module: "ESNext",
496
+ moduleResolution: "node",
497
+ outDir: "./dist",
498
+ rootDir: "./src",
499
+ strict: true,
500
+ esModuleInterop: true,
501
+ skipLibCheck: true,
502
+ forceConsistentCasingInFileNames: true,
503
+ declaration: true,
504
+ declarationMap: true,
505
+ sourceMap: true,
506
+ allowSyntheticDefaultImports: true,
507
+ resolveJsonModule: true
508
+ },
509
+ include: ["src/**/*"],
510
+ exclude: ["node_modules", "dist", "src/telescope/**/*", "src/telescope-examples/**/*"]
511
+ };
512
+ }
513
+ function generateReadme(packageName) {
514
+ return `# ${packageName.charAt(0).toUpperCase() + packageName.slice(1)} MCP Server
515
+
516
+ This MCP server provides AI agents with tools to interact with blockchain through generated TypeScript clients.
517
+
518
+ **Note**: This MCP server contains a complete copy of the telescope generated codebase in \`src/telescope/\` for AI agents to reference, but uses mock implementations for demonstration. The telescope code is excluded from the build process.
519
+
520
+ ## Installation
521
+
522
+ \`\`\`bash
523
+ cd ${packageName}-mcp
524
+ npm install
525
+ npm run build
526
+ \`\`\`
527
+
528
+ ## Usage with AI Agents
529
+
530
+ Add this configuration to your AI agent's MCP settings:
531
+
532
+ \`\`\`json
533
+ {
534
+ "mcpServers": {
535
+ "${packageName}-mcp-server": {
536
+ "command": "node",
537
+ "args": ["/path/to/${packageName}-mcp/dist/index.js"]
538
+ }
539
+ }
540
+ }
541
+ \`\`\`
542
+
543
+ ## Available Features
544
+
545
+ This MCP server provides:
546
+
547
+ - **Comprehensive Examples**: Reference implementations in \`src/telescope-examples/\`
548
+ - **Function Generator Tool**: AI-powered tool that creates custom blockchain functions based on user requirements
549
+ - **AI Guidance**: Prompt files to help AI agents understand blockchain development
550
+ - **Complete Codebase**: Full telescope-generated code in \`src/telescope/\` for reference
551
+
552
+ **Note**: The MCP server uses a meta-tool approach - instead of predefined tools, it instructs agents to create custom functions by referencing the comprehensive examples.
553
+
554
+ ## Development
555
+
556
+ \`\`\`bash
557
+ npm run build # Build the server
558
+ npm run inspector # Run MCP inspector for testing
559
+ npm run clean # Clean dist directory
560
+ \`\`\`
561
+
562
+ ## Directory Structure
563
+
564
+ \`\`\`
565
+ ${packageName}-mcp/
566
+ ├── src/
567
+ │ ├── telescope/ # 📚 Telescope generated code (reference only, excluded from build)
568
+ │ │ ├── cosmos/ # Full cosmos SDK modules
569
+ │ │ │ ├── bank/ # Balance queries, transfers
570
+ │ │ │ ├── staking/ # Validator operations
571
+ │ │ │ └── ... # Other cosmos modules
572
+ │ │ ├── osmosis/ # Osmosis DEX functionality
573
+ │ │ ├── ibc/ # Inter-blockchain communication
574
+ │ │ └── index.ts # Main exports
575
+ │ ├── telescope-examples/ # 📖 Usage examples and patterns (excluded from build)
576
+ │ │ ├── config-example.ts # Chain configuration setup
577
+ │ │ ├── useBalance.ts # Balance query React hooks
578
+ │ │ ├── useBalanceFunc.ts # Direct balance functions
579
+ │ │ ├── getBalance.ts # Balance queries with examples
580
+ │ │ ├── useAssets.ts # Multi-token balance queries
581
+ │ │ ├── useStakingData.ts # Staking and delegation info
582
+ │ │ ├── useValidators.ts # Validator queries
583
+ │ │ ├── useVoting.ts # Governance proposals
584
+ │ │ ├── useContractInfo.ts # Smart contract queries
585
+ │ │ ├── useMyContracts.ts # User's contract list
586
+ │ │ ├── useGrants.ts # Authorization grants
587
+ │ │ └── useSendData.ts # Transaction preparation
588
+ │ ├── prompts/ # 🤖 Agent instruction files
589
+ │ │ ├── codegen-usage.md # Telescope usage guide
590
+ │ │ ├── agent-guidelines.md # Best practices for agents
591
+ │ │ └── chains.json # Chain registry data
592
+ │ ├── index.ts # MCP server with function generator tool
593
+ │ └── telescope-loader.ts # Utility for dynamic code loading
594
+ ├── dist/ # Compiled JavaScript (excludes telescope/ and telescope-examples/)
595
+ └── package.json
596
+ \`\`\`
597
+
598
+ The \`src/telescope/\` and \`src/telescope-examples/\` directories contain reference code for AI agents but are excluded from the TypeScript build process.
599
+
600
+ Generated by [Telescope](https://github.com/hyperweb-io/telescope) 🔭
601
+ `;
602
+ }
603
+ function copyTelescopeCodebase(builder, mcpServerPath, packageName) {
604
+ const sourcePath = builder.outPath;
605
+ const destPath = join(mcpServerPath, 'src', 'telescope');
606
+ // Copy the entire telescope generated directory
607
+ if (existsSync(sourcePath)) {
608
+ // Skip copy if destination already exists (avoids Windows file permission issues)
609
+ if (existsSync(destPath)) {
610
+ console.log(`Telescope codebase already exists at ${destPath}, skipping copy to avoid Windows file permission issues`);
611
+ return;
612
+ }
613
+ console.log(`Copying telescope codebase from ${sourcePath} to ${destPath}`);
614
+ // Ensure parent directory exists
615
+ mkdirSync(dirname(destPath), { recursive: true });
616
+ // Copy without removing destination first
617
+ try {
618
+ cpSync(sourcePath, destPath, { recursive: true, force: true });
619
+ }
620
+ catch (error) {
621
+ console.warn(`Warning: Could not copy telescope codebase: ${error}`);
622
+ console.log('MCP server will still function, but AI agents will have limited code references');
623
+ // Don't throw error - let MCP server generation continue
624
+ }
625
+ }
626
+ else {
627
+ console.warn(`Source path ${sourcePath} does not exist, skipping telescope codebase copy`);
628
+ }
629
+ }
630
+ // Removed retry logic - no longer needed since we skip copy if destination exists
631
+ function generateTelescopeLoader(packageName) {
632
+ return `import { readFileSync } from 'node:fs';
633
+ import { resolve, dirname } from 'node:path';
634
+ import { fileURLToPath } from 'node:url';
635
+
636
+ const __filename = fileURLToPath(import.meta.url);
637
+ const __dirname = dirname(__filename);
638
+
639
+ /**
640
+ * Load telescope generated modules dynamically
641
+ * This utility helps MCP tools access the telescope codebase
642
+ */
643
+ export class TelescopeLoader {
644
+ private basePath: string;
645
+
646
+ constructor() {
647
+ this.basePath = resolve(__dirname, 'telescope');
648
+ }
649
+
650
+ /**
651
+ * Get available modules in the telescope codebase
652
+ */
653
+ getAvailableModules(): string[] {
654
+ // This would typically read the directory structure
655
+ // For now, return common cosmos modules
656
+ return [
657
+ 'cosmos/bank/v1beta1',
658
+ 'cosmos/staking/v1beta1',
659
+ 'cosmos/gov/v1beta1',
660
+ 'cosmos/distribution/v1beta1',
661
+ 'cosmwasm/wasm/v1',
662
+ 'ibc/core/client/v1',
663
+ 'osmosis/gamm/v1beta1'
664
+ ];
665
+ }
666
+
667
+ /**
668
+ * Load module documentation/examples
669
+ */
670
+ loadModuleInfo(modulePath: string) {
671
+ try {
672
+ const infoPath = resolve(this.basePath, modulePath, 'README.md');
673
+ return readFileSync(infoPath, 'utf-8');
674
+ } catch (error) {
675
+ return \`Module documentation not found for \${modulePath}\`;
676
+ }
677
+ }
678
+
679
+ /**
680
+ * Get module schema information
681
+ */
682
+ getModuleSchema(modulePath: string) {
683
+ // Return basic schema info for the module
684
+ return {
685
+ module: modulePath,
686
+ package: '${packageName}',
687
+ queries: ['getBalance', 'getAllBalances'],
688
+ mutations: ['send', 'delegate'],
689
+ types: ['Coin', 'MsgSend', 'MsgDelegate']
690
+ };
691
+ }
692
+ }
693
+
694
+ export const telescopeLoader = new TelescopeLoader();
695
+ `;
696
+ }
697
+ function generateComprehensivePrompts(mcpServerPath, packageName) {
698
+ // Generate codegen-usage.md
699
+ const codegenUsageContent = `# Codegen Usage Guide
700
+
701
+ ## Overview
702
+ This guide provides instructions for MCP agents on how to use the telescope generated code in the ${packageName} package.
703
+
704
+ ## Category of Functions
705
+
706
+ ### 1. **.rpc.func** - Direct Function Calls
707
+ These are direct async functions that make RPC calls to blockchain nodes. Use these for:
708
+ - Server-side operations
709
+ - Node.js scripts
710
+ - Direct blockchain queries outside React
711
+
712
+ **Import Pattern**:
713
+ \`\`\`typescript
714
+ import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
715
+ import { send } from '${packageName}/cosmos/bank/v1beta1/tx.rpc.func';
716
+ \`\`\`
717
+
718
+ **Usage Examples**:
719
+
720
+ **Query Balance**:
721
+ \`\`\`typescript
722
+ import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
723
+
724
+ // Basic balance query
725
+ const { balance } = await getBalance(rpcEndpoint, {
726
+ address: "cosmos1...",
727
+ denom: "uatom"
728
+ });
729
+
730
+ // With error handling
731
+ try {
732
+ const { balance } = await getBalance(rpcEndpoint, { address, denom });
733
+ const atomAmount = Number(balance?.amount || 0) / Math.pow(10, 6); // Convert uatom to ATOM
734
+ return atomAmount;
735
+ } catch (error) {
736
+ console.error('Error fetching balance:', error);
737
+ return null;
738
+ }
739
+ \`\`\`
740
+
741
+ ### 2. **.rpc.react** - React Hooks
742
+ These are React hooks for frontend applications. They provide:
743
+ - Automatic caching and refetching
744
+ - Loading states
745
+ - Error handling
746
+ - Integration with React Query
747
+
748
+ **Import Pattern**:
749
+ \`\`\`typescript
750
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
751
+ import { useSend } from '${packageName}/cosmos/bank/v1beta1/tx.rpc.react';
752
+ \`\`\`
753
+
754
+ ## Chain Configuration Setup
755
+
756
+ ### Import Chain Registry Data
757
+ \`\`\`typescript
758
+ import { assetLists, chains } from "@chain-registry/v2";
759
+ \`\`\`
760
+
761
+ ### Basic Configuration
762
+ \`\`\`typescript
763
+ // Define your target chain
764
+ export const defaultChainName = 'cosmos'; // or 'osmosis', 'injective', etc.
765
+
766
+ // Find chain info from registry
767
+ export const defaultChain = chains.find((chain) => chain.chainName === defaultChainName);
768
+
769
+ // Get RPC endpoint
770
+ export const defaultRpcEndpoint = defaultChain?.apis?.rpc?.[0]?.address || 'http://localhost:26657';
771
+ \`\`\`
772
+
773
+ ## Detailed Examples Reference
774
+
775
+ ### Using src/telescope-examples Directory
776
+ When you need more specific implementation details or complex use cases, reference the example files in \`src/telescope-examples/\`. These are real-world examples for production usage.
777
+
778
+ ### Using src/tools Directory
779
+ The \`src/tools/\` directory contains MCP tool implementations that demonstrate how to use the telescope-examples in MCP tools. These tools show patterns for:
780
+ - Importing functions from telescope-examples
781
+ - Handling errors and returning proper MCP responses
782
+ - Working with blockchain data in MCP context
783
+
784
+ Each tool in \`src/tools/\` corresponds to functionality in \`src/telescope-examples/\` and shows how to bridge the gap between React hooks/utility functions and MCP tool implementations.
785
+
786
+ ## Important Notes
787
+
788
+ ### Function Categories Usage
789
+ - **Use .rpc.func** for: Server-side scripts, CLI tools, backend services
790
+ - **Use .rpc.react** for: React applications, frontend components with state management
791
+
792
+ ### Error Handling Patterns
793
+ \`\`\`typescript
794
+ // For .rpc.func
795
+ try {
796
+ const result = await getBalance(rpcEndpoint, { address, denom });
797
+ return result;
798
+ } catch (error) {
799
+ if (error.message.includes('not found')) {
800
+ return null; // Handle account not found
801
+ }
802
+ throw error; // Re-throw other errors
803
+ }
804
+ \`\`\`
805
+ `;
806
+ writeFileSync(join(mcpServerPath, 'src', 'prompts', 'codegen-usage.md'), codegenUsageContent);
807
+ // Generate agent-guidelines.md
808
+ const agentGuidelinesContent = `# MCP Agent Guidelines
809
+
810
+ ## Overview
811
+ These guidelines help MCP agents provide helpful, accurate, and safe blockchain interactions using the ${packageName} library.
812
+
813
+ ## General Principles
814
+
815
+ ### 1. Safety First
816
+ - **Never expose private keys or mnemonics**
817
+ - **Always validate addresses before operations**
818
+ - **Warn users about irreversible operations**
819
+ - **Explain risks (slashing, unbonding periods, etc.)**
820
+
821
+ ### 2. User-Friendly Communication
822
+ - **Convert base units to human-readable amounts** (uatom → ATOM)
823
+ - **Use clear, non-technical language when possible**
824
+ - **Provide context for blockchain-specific concepts**
825
+ - **Show approximate USD values when helpful**
826
+
827
+ ### 3. Accuracy and Reliability
828
+ - **Always handle errors gracefully**
829
+ - **Provide accurate information about fees and timing**
830
+ - **Double-check calculations and conversions**
831
+ - **Verify data freshness and warn about stale data**
832
+
833
+ ## Response Patterns
834
+
835
+ ### When User Asks About Balances
836
+ \`\`\`
837
+ ✅ Good Response:
838
+ "You have 12.5 ATOM (12,500,000 uatom) in your wallet. This is worth approximately $150 USD at current prices. You also have 0.05 ATOM available to pay for transaction fees."
839
+
840
+ ❌ Poor Response:
841
+ "Balance: 12500000"
842
+ \`\`\`
843
+
844
+ ## Data Formatting Guidelines
845
+
846
+ ### Amounts
847
+ Always convert from base units:
848
+ \`\`\`typescript
849
+ // Good
850
+ const atomAmount = parseInt(balance.amount) / 1_000_000;
851
+ return \`$\{atomAmount} ATOM\`;
852
+
853
+ // Bad
854
+ return \`$\{balance.amount} uatom\`;
855
+ \`\`\`
856
+
857
+ ### Addresses
858
+ Abbreviate long addresses for readability:
859
+ \`\`\`typescript
860
+ const formatAddress = (addr: string) => {
861
+ return \`$\{addr.slice(0, 10)}...$\{addr.slice(-4)}\`;
862
+ };
863
+ // cosmos1abc123...xyz9
864
+ \`\`\`
865
+
866
+ ## Security Guidelines
867
+
868
+ ### Address Validation
869
+ \`\`\`typescript
870
+ const validateCosmosAddress = (address: string): boolean => {
871
+ return address.startsWith('cosmos1') && address.length === 45;
872
+ };
873
+ \`\`\`
874
+
875
+ ### Amount Validation
876
+ \`\`\`typescript
877
+ const validateAmount = (amount: string): boolean => {
878
+ const num = parseFloat(amount);
879
+ return !isNaN(num) && num > 0 && num < 1e15; // Reasonable limits
880
+ };
881
+ \`\`\`
882
+ `;
883
+ writeFileSync(join(mcpServerPath, 'src', 'prompts', 'agent-guidelines.md'), agentGuidelinesContent);
884
+ // Copy chains.json from chain-registry (this is a large static file)
885
+ const chainsJsonContent = `[
886
+ {
887
+ "$schema": "../chain.schema.json",
888
+ "chainName": "cosmos",
889
+ "status": "live",
890
+ "networkType": "mainnet",
891
+ "prettyName": "Cosmos Hub",
892
+ "chainId": "cosmoshub-4",
893
+ "bech32Prefix": "cosmos",
894
+ "daemonName": "gaiad",
895
+ "nodeHome": "$HOME/.gaia",
896
+ "slip44": 118,
897
+ "apis": {
898
+ "rpc": [
899
+ {
900
+ "address": "https://cosmos-rpc.quickapi.com:443"
901
+ }
902
+ ],
903
+ "rest": [
904
+ {
905
+ "address": "https://cosmos-rest.quickapi.com:443"
906
+ }
907
+ ]
908
+ }
909
+ },
910
+ {
911
+ "chainName": "osmosis",
912
+ "status": "live",
913
+ "networkType": "mainnet",
914
+ "prettyName": "Osmosis",
915
+ "chainId": "osmosis-1",
916
+ "bech32Prefix": "osmo",
917
+ "daemonName": "osmosisd",
918
+ "nodeHome": "$HOME/.osmosisd",
919
+ "slip44": 118,
920
+ "apis": {
921
+ "rpc": [
922
+ {
923
+ "address": "https://osmosis-rpc.quickapi.com:443"
924
+ }
925
+ ],
926
+ "rest": [
927
+ {
928
+ "address": "https://osmosis-rest.quickapi.com:443"
929
+ }
930
+ ]
931
+ }
932
+ },
933
+ {
934
+ "chainName": "injective",
935
+ "status": "live",
936
+ "networkType": "mainnet",
937
+ "prettyName": "Injective",
938
+ "chainId": "injective-1",
939
+ "bech32Prefix": "inj",
940
+ "daemonName": "injectived",
941
+ "nodeHome": "$HOME/.injectived",
942
+ "slip44": 60,
943
+ "apis": {
944
+ "rpc": [
945
+ {
946
+ "address": "https://injective-rpc.quickapi.com:443"
947
+ }
948
+ ],
949
+ "rest": [
950
+ {
951
+ "address": "https://injective-rest.quickapi.com:443"
952
+ }
953
+ ]
954
+ }
955
+ }
956
+ ]`;
957
+ writeFileSync(join(mcpServerPath, 'src', 'prompts', 'chains.json'), chainsJsonContent);
958
+ }
959
+ function generateTelescopeExamples(mcpServerPath, packageName) {
960
+ const exampleFiles = [
961
+ {
962
+ name: 'config-example.ts',
963
+ content: `import { assetLists, chains } from "@chain-registry/v2";
964
+
965
+ /**
966
+ * mainnet: 'cosmos'
967
+ * testnet: 'cosmoshub-testnet'
968
+ * mainnet rpc: 'https://cosmos-rpc.quickapi.com:443'
969
+ * testnet rpc: 'https://rpc.testnet.cosmos.network:443'
970
+ */
971
+ export const defaultChainName = 'cosmos'
972
+ export const defaultRpcEndpoint = 'https://cosmos-rpc.quickapi.com:443'
973
+
974
+ export const defaultChain = chains.find((chain) => chain.chainName === defaultChainName)
975
+
976
+ export const defaultAssetList = assetLists.find((assetList) => assetList.chainName === defaultChainName)
977
+ `
978
+ },
979
+ {
980
+ name: 'useBalance.ts',
981
+ content: `import { useChain } from '@interchain-kit/react';
982
+ import { defaultContext } from '@tanstack/react-query';
983
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
984
+
985
+ export const useBalance = (
986
+ chainName: string,
987
+ enabled: boolean = true,
988
+ displayDenom?: string
989
+ ) => {
990
+ const { address, assetList } = useChain(chainName);
991
+
992
+ let denom = assetList?.assets[0].base!;
993
+ for (const asset of assetList?.assets || []) {
994
+ if (asset.display.toLowerCase() === displayDenom?.toLowerCase()) {
995
+ denom = asset.base;
996
+ break;
997
+ }
998
+ }
999
+
1000
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443'; // Use dynamic endpoint
1001
+
1002
+ const isReady = !!address && !!rpcEndpoint;
1003
+
1004
+ const balanceQuery = useGetBalance({
1005
+ request: {
1006
+ denom,
1007
+ address: address || '',
1008
+ },
1009
+ options: {
1010
+ enabled: isReady && enabled,
1011
+ select: ({ balance }) => balance,
1012
+ context: defaultContext,
1013
+ },
1014
+ clientResolver: rpcEndpoint,
1015
+ customizedQueryKey: ['balance', address, denom],
1016
+ });
1017
+
1018
+ return {
1019
+ balance: balanceQuery.data,
1020
+ isLoading: balanceQuery.isFetching,
1021
+ };
1022
+ };
1023
+ `
1024
+ },
1025
+ {
1026
+ name: 'useBalanceReact.ts',
1027
+ content: `import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1028
+ import { defaultRpcEndpoint as rpcEndpoint } from '@/config';
1029
+ import BigNumber from 'bignumber.js';
1030
+ import { defaultAssetList } from '@/config';
1031
+ import { defaultContext } from '@tanstack/react-query';
1032
+
1033
+ export default function useBalance({ address }: { address: string }) {
1034
+ const coin = defaultAssetList?.assets[0];
1035
+
1036
+ const denom = coin!.base!;
1037
+
1038
+ const COIN_DISPLAY_EXPONENT = coin!.denomUnits.find(
1039
+ (unit) => unit.denom === coin!.display
1040
+ )?.exponent as number;
1041
+
1042
+ const {
1043
+ data: balance,
1044
+ isSuccess: isBalanceLoaded,
1045
+ isLoading: isFetchingBalance,
1046
+ refetch: refetchBalance,
1047
+ } = useGetBalance({
1048
+ request: {
1049
+ address: address || '',
1050
+ denom,
1051
+ },
1052
+ options: {
1053
+ context: defaultContext,
1054
+ enabled: !!address,
1055
+ select: ({ balance }) =>
1056
+ new BigNumber(balance?.amount ?? 0).multipliedBy(
1057
+ 10 ** -COIN_DISPLAY_EXPONENT
1058
+ ),
1059
+ staleTime: 0,
1060
+ },
1061
+ clientResolver: rpcEndpoint,
1062
+ });
1063
+
1064
+ return {
1065
+ balance,
1066
+ isBalanceLoaded,
1067
+ isFetchingBalance,
1068
+ refetchBalance,
1069
+ };
1070
+ }
1071
+ `
1072
+ },
1073
+ {
1074
+ name: 'useBalanceFunc.ts',
1075
+ content: `import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
1076
+ import { defaultRpcEndpoint } from '@/config';
1077
+
1078
+ export const useBalanceFunc = async (address: string, denom: string) => {
1079
+ try {
1080
+ const { balance } = await getBalance(defaultRpcEndpoint, {
1081
+ address,
1082
+ denom,
1083
+ });
1084
+
1085
+ return {
1086
+ balance: balance?.amount || '0',
1087
+ denom: balance?.denom || denom,
1088
+ };
1089
+ } catch (error) {
1090
+ console.error('Error fetching balance:', error);
1091
+ return {
1092
+ balance: '0',
1093
+ denom,
1094
+ };
1095
+ }
1096
+ };
1097
+ `
1098
+ },
1099
+ {
1100
+ name: 'getBalance.ts',
1101
+ content: `import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
1102
+ import { send } from '${packageName}/cosmos/bank/v1beta1/tx.rpc.func';
1103
+ import { MsgSend } from '${packageName}/cosmos/bank/v1beta1/tx';
1104
+
1105
+ const main = async () => {
1106
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1107
+ const denom = 'uatom';
1108
+ const address = 'cosmos1...'; // Your address here
1109
+
1110
+ // Query balance
1111
+ const { balance } = await getBalance(rpcEndpoint, {
1112
+ address,
1113
+ denom,
1114
+ });
1115
+
1116
+ console.log(\`Balance: \${balance?.amount} \${denom}\`);
1117
+
1118
+ // Example: Send transaction (requires signer setup)
1119
+ /*
1120
+ const fee = {
1121
+ amount: [{ denom, amount: '5000' }],
1122
+ gas: '200000',
1123
+ };
1124
+
1125
+ const token = {
1126
+ amount: '1000000',
1127
+ denom,
1128
+ };
1129
+
1130
+ const msg = MsgSend.fromPartial({
1131
+ fromAddress: address,
1132
+ toAddress: 'cosmos1recipient...',
1133
+ amount: [token],
1134
+ });
1135
+
1136
+ // const tx = await send(signer, address, msg, fee, 'Payment');
1137
+ */
1138
+ };
1139
+
1140
+ main().catch(console.error);
1141
+ `
1142
+ },
1143
+ {
1144
+ name: 'useAssets.ts',
1145
+ content: `import { useMemo } from 'react';
1146
+ import { useChain } from '@interchain-kit/react';
1147
+ import { defaultContext } from '@tanstack/react-query';
1148
+ import BigNumber from 'bignumber.js';
1149
+ import { useGetAllBalances } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1150
+ import { Coin } from '${packageName}/types';
1151
+
1152
+ export const useAssets = (chainName: string) => {
1153
+ const { address } = useChain(chainName);
1154
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1155
+
1156
+ const isReady = !!address && !!rpcEndpoint;
1157
+
1158
+ const allBalancesQuery = useGetAllBalances({
1159
+ request: {
1160
+ address: address || '',
1161
+ pagination: {
1162
+ key: new Uint8Array(),
1163
+ offset: 0n,
1164
+ limit: 100n,
1165
+ countTotal: true,
1166
+ reverse: false,
1167
+ },
1168
+ resolveDenom: false,
1169
+ },
1170
+ options: {
1171
+ enabled: isReady,
1172
+ select: ({ balances }) => balances || [],
1173
+ context: defaultContext,
1174
+ },
1175
+ clientResolver: rpcEndpoint,
1176
+ customizedQueryKey: ['allBalances', address],
1177
+ });
1178
+
1179
+ const data = useMemo(() => {
1180
+ if (!allBalancesQuery.data) return;
1181
+
1182
+ const assets = allBalancesQuery.data.map(({ amount, denom }) => ({
1183
+ symbol: denom.toUpperCase(),
1184
+ displayAmount: new BigNumber(amount).dividedBy(1e6).toString(),
1185
+ amount,
1186
+ denom,
1187
+ }));
1188
+
1189
+ return { assets };
1190
+ }, [allBalancesQuery.data]);
1191
+
1192
+ return {
1193
+ data,
1194
+ isLoading: allBalancesQuery.isLoading,
1195
+ refetch: allBalancesQuery.refetch
1196
+ };
1197
+ };
1198
+ `
1199
+ },
1200
+ {
1201
+ name: 'useStakingData.ts',
1202
+ content: `import { useMemo } from 'react';
1203
+ import { useChain } from '@interchain-kit/react';
1204
+ import BigNumber from 'bignumber.js';
1205
+ import {
1206
+ BondStatus,
1207
+ bondStatusToJSON,
1208
+ } from '${packageName}/cosmos/staking/v1beta1/staking';
1209
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1210
+ import {
1211
+ useGetDelegatorValidators,
1212
+ useGetDelegatorDelegations,
1213
+ useGetValidators,
1214
+ useGetParams as useStakingParams,
1215
+ useGetPool,
1216
+ } from '${packageName}/cosmos/staking/v1beta1/query.rpc.react';
1217
+ import {
1218
+ useGetDelegationTotalRewards,
1219
+ useGetParams as useDistributionParams,
1220
+ } from '${packageName}/cosmos/distribution/v1beta1/query.rpc.react';
1221
+ import { useGetAnnualProvisions } from '${packageName}/cosmos/mint/v1beta1/query.rpc.react';
1222
+ import { defaultContext } from '@tanstack/react-query';
1223
+
1224
+ export const useStakingData = (chainName: string) => {
1225
+ const { address, assetList } = useChain(chainName);
1226
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1227
+
1228
+ const coin = assetList?.assets[0];
1229
+ const denom = coin?.base || 'uatom';
1230
+
1231
+ const isDataQueryEnabled = !!address && !!rpcEndpoint;
1232
+
1233
+ const balanceQuery = useGetBalance({
1234
+ request: {
1235
+ address: address || '',
1236
+ denom,
1237
+ },
1238
+ options: {
1239
+ context: defaultContext,
1240
+ enabled: isDataQueryEnabled,
1241
+ select: ({ balance }) => balance?.amount || '0',
1242
+ refetchOnMount: 'always',
1243
+ },
1244
+ clientResolver: rpcEndpoint,
1245
+ });
1246
+
1247
+ const validatorsQuery = useGetValidators({
1248
+ request: {
1249
+ status: bondStatusToJSON(BondStatus.BOND_STATUS_BONDED),
1250
+ pagination: {
1251
+ key: new Uint8Array(),
1252
+ offset: 0n,
1253
+ limit: 200n,
1254
+ countTotal: true,
1255
+ reverse: false,
1256
+ },
1257
+ },
1258
+ options: {
1259
+ context: defaultContext,
1260
+ enabled: isDataQueryEnabled,
1261
+ select: ({ validators }) => {
1262
+ return validators.sort((a, b) =>
1263
+ new BigNumber(b.tokens).minus(a.tokens).toNumber(),
1264
+ );
1265
+ },
1266
+ },
1267
+ clientResolver: rpcEndpoint,
1268
+ customizedQueryKey: ['validators', chainName],
1269
+ });
1270
+
1271
+ const delegationsQuery = useGetDelegatorDelegations({
1272
+ request: {
1273
+ delegatorAddr: address || '',
1274
+ pagination: {
1275
+ key: new Uint8Array(),
1276
+ offset: 0n,
1277
+ limit: 100n,
1278
+ countTotal: true,
1279
+ reverse: false,
1280
+ },
1281
+ },
1282
+ options: {
1283
+ context: defaultContext,
1284
+ enabled: isDataQueryEnabled,
1285
+ select: ({ delegationResponses }) => delegationResponses,
1286
+ },
1287
+ clientResolver: rpcEndpoint,
1288
+ });
1289
+
1290
+ const rewardsQuery = useGetDelegationTotalRewards({
1291
+ request: {
1292
+ delegatorAddress: address || '',
1293
+ },
1294
+ options: {
1295
+ context: defaultContext,
1296
+ enabled: isDataQueryEnabled,
1297
+ select: (data) => data,
1298
+ },
1299
+ clientResolver: rpcEndpoint,
1300
+ });
1301
+
1302
+ const allQueries = {
1303
+ balance: balanceQuery,
1304
+ validators: validatorsQuery,
1305
+ delegations: delegationsQuery,
1306
+ rewards: rewardsQuery,
1307
+ };
1308
+
1309
+ const isLoading = Object.values(allQueries).some(
1310
+ ({ isLoading }) => isLoading,
1311
+ );
1312
+
1313
+ const data = useMemo(() => {
1314
+ if (isLoading) return;
1315
+
1316
+ return {
1317
+ balance: balanceQuery.data,
1318
+ validators: validatorsQuery.data,
1319
+ delegations: delegationsQuery.data,
1320
+ rewards: rewardsQuery.data,
1321
+ };
1322
+ }, [isLoading, balanceQuery.data, validatorsQuery.data, delegationsQuery.data, rewardsQuery.data]);
1323
+
1324
+ const refetch = () => {
1325
+ Object.values(allQueries).forEach((query) => query.refetch());
1326
+ };
1327
+
1328
+ return { data, isLoading, refetch };
1329
+ };
1330
+ `
1331
+ },
1332
+ {
1333
+ name: 'useValidators.ts',
1334
+ content: `import { useMemo } from 'react';
1335
+ import { BondStatus, bondStatusToJSON } from '${packageName}/cosmos/staking/v1beta1/staking';
1336
+ import { useGetValidators } from '${packageName}/cosmos/staking/v1beta1/query.rpc.react';
1337
+ import { defaultContext } from '@tanstack/react-query';
1338
+ import BigNumber from 'bignumber.js';
1339
+
1340
+ export const useValidators = (chainName: string) => {
1341
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1342
+
1343
+ const validatorsQuery = useGetValidators({
1344
+ request: {
1345
+ status: bondStatusToJSON(BondStatus.BOND_STATUS_BONDED),
1346
+ pagination: {
1347
+ key: new Uint8Array(),
1348
+ offset: 0n,
1349
+ limit: 200n,
1350
+ countTotal: true,
1351
+ reverse: false,
1352
+ },
1353
+ },
1354
+ options: {
1355
+ context: defaultContext,
1356
+ enabled: !!rpcEndpoint,
1357
+ select: ({ validators }) => {
1358
+ return validators
1359
+ .sort((a, b) => new BigNumber(b.tokens).minus(a.tokens).toNumber())
1360
+ .map((validator) => ({
1361
+ operatorAddress: validator.operatorAddress,
1362
+ moniker: validator.description?.moniker || '',
1363
+ tokens: validator.tokens,
1364
+ delegatorShares: validator.delegatorShares,
1365
+ commission: validator.commission?.commissionRates?.rate || '0',
1366
+ status: validator.status,
1367
+ jailed: validator.jailed,
1368
+ }));
1369
+ },
1370
+ },
1371
+ clientResolver: rpcEndpoint,
1372
+ customizedQueryKey: ['validators', chainName],
1373
+ });
1374
+
1375
+ return {
1376
+ data: validatorsQuery.data,
1377
+ isLoading: validatorsQuery.isLoading,
1378
+ refetch: validatorsQuery.refetch,
1379
+ };
1380
+ };
1381
+ `
1382
+ },
1383
+ {
1384
+ name: 'useVoting.ts',
1385
+ content: `import { useMemo } from 'react';
1386
+ import { useGetProposals } from '${packageName}/cosmos/gov/v1beta1/query.rpc.react';
1387
+ import { ProposalStatus, proposalStatusToJSON } from '${packageName}/cosmos/gov/v1beta1/gov';
1388
+ import { defaultContext } from '@tanstack/react-query';
1389
+
1390
+ export const useVoting = (chainName: string) => {
1391
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1392
+
1393
+ const proposalsQuery = useGetProposals({
1394
+ request: {
1395
+ proposalStatus: proposalStatusToJSON(ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD),
1396
+ voter: '',
1397
+ depositor: '',
1398
+ pagination: {
1399
+ key: new Uint8Array(),
1400
+ offset: 0n,
1401
+ limit: 50n,
1402
+ countTotal: true,
1403
+ reverse: true,
1404
+ },
1405
+ },
1406
+ options: {
1407
+ context: defaultContext,
1408
+ enabled: !!rpcEndpoint,
1409
+ select: ({ proposals }) => proposals,
1410
+ },
1411
+ clientResolver: rpcEndpoint,
1412
+ customizedQueryKey: ['proposals', chainName],
1413
+ });
1414
+
1415
+ const data = useMemo(() => {
1416
+ if (!proposalsQuery.data) return;
1417
+
1418
+ return {
1419
+ proposals: proposalsQuery.data.map((proposal) => ({
1420
+ proposalId: proposal.proposalId.toString(),
1421
+ title: proposal.content?.title || '',
1422
+ description: proposal.content?.description || '',
1423
+ status: proposal.status,
1424
+ submitTime: proposal.submitTime,
1425
+ votingStartTime: proposal.votingStartTime,
1426
+ votingEndTime: proposal.votingEndTime,
1427
+ })),
1428
+ };
1429
+ }, [proposalsQuery.data]);
1430
+
1431
+ return {
1432
+ data,
1433
+ isLoading: proposalsQuery.isLoading,
1434
+ refetch: proposalsQuery.refetch,
1435
+ };
1436
+ };
1437
+ `
1438
+ },
1439
+ {
1440
+ name: 'useVotingData.ts',
1441
+ content: `import { useMemo } from 'react';
1442
+ import { useChain } from '@interchain-kit/react';
1443
+ import {
1444
+ useGetProposals,
1445
+ useGetVote,
1446
+ useGetTallyResult,
1447
+ } from '${packageName}/cosmos/gov/v1beta1/query.rpc.react';
1448
+ import { ProposalStatus, proposalStatusToJSON } from '${packageName}/cosmos/gov/v1beta1/gov';
1449
+ import { defaultContext } from '@tanstack/react-query';
1450
+
1451
+ export const useVotingData = (chainName: string) => {
1452
+ const { address } = useChain(chainName);
1453
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1454
+
1455
+ const isEnabled = !!rpcEndpoint;
1456
+
1457
+ const proposalsQuery = useGetProposals({
1458
+ request: {
1459
+ proposalStatus: proposalStatusToJSON(ProposalStatus.PROPOSAL_STATUS_UNSPECIFIED),
1460
+ voter: '',
1461
+ depositor: '',
1462
+ pagination: {
1463
+ key: new Uint8Array(),
1464
+ offset: 0n,
1465
+ limit: 100n,
1466
+ countTotal: true,
1467
+ reverse: true,
1468
+ },
1469
+ },
1470
+ options: {
1471
+ context: defaultContext,
1472
+ enabled: isEnabled,
1473
+ select: ({ proposals }) => proposals,
1474
+ },
1475
+ clientResolver: rpcEndpoint,
1476
+ customizedQueryKey: ['allProposals', chainName],
1477
+ });
1478
+
1479
+ const activeProposals = useMemo(() => {
1480
+ return proposalsQuery.data?.filter(
1481
+ (proposal) => proposal.status === ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD
1482
+ ) || [];
1483
+ }, [proposalsQuery.data]);
1484
+
1485
+ const data = useMemo(() => {
1486
+ if (!proposalsQuery.data) return;
1487
+
1488
+ const categorized = {
1489
+ active: activeProposals,
1490
+ passed: proposalsQuery.data.filter(
1491
+ (p) => p.status === ProposalStatus.PROPOSAL_STATUS_PASSED
1492
+ ),
1493
+ rejected: proposalsQuery.data.filter(
1494
+ (p) => p.status === ProposalStatus.PROPOSAL_STATUS_REJECTED
1495
+ ),
1496
+ failed: proposalsQuery.data.filter(
1497
+ (p) => p.status === ProposalStatus.PROPOSAL_STATUS_FAILED
1498
+ ),
1499
+ };
1500
+
1501
+ return {
1502
+ proposals: proposalsQuery.data,
1503
+ categorized,
1504
+ activeCount: categorized.active.length,
1505
+ };
1506
+ }, [proposalsQuery.data, activeProposals]);
1507
+
1508
+ return {
1509
+ data,
1510
+ isLoading: proposalsQuery.isLoading,
1511
+ refetch: proposalsQuery.refetch,
1512
+ };
1513
+ };
1514
+ `
1515
+ },
1516
+ {
1517
+ name: 'useContractInfo.ts',
1518
+ content: `import { defaultContext } from '@tanstack/react-query';
1519
+ import { useGetContractInfo } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1520
+
1521
+ export const useContractInfo = ({
1522
+ contractAddress,
1523
+ enabled = true,
1524
+ }: {
1525
+ contractAddress: string;
1526
+ enabled?: boolean;
1527
+ }) => {
1528
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1529
+
1530
+ return useGetContractInfo({
1531
+ request: {
1532
+ address: contractAddress,
1533
+ },
1534
+ options: {
1535
+ enabled: !!contractAddress && !!rpcEndpoint && enabled,
1536
+ context: defaultContext,
1537
+ },
1538
+ clientResolver: rpcEndpoint,
1539
+ });
1540
+ };
1541
+ `
1542
+ },
1543
+ {
1544
+ name: 'useQueryContract.ts',
1545
+ content: `import { defaultContext } from '@tanstack/react-query';
1546
+ import { useGetSmartContractState } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1547
+
1548
+ export const useQueryContract = ({
1549
+ contractAddress,
1550
+ queryMsg,
1551
+ enabled = true,
1552
+ }: {
1553
+ contractAddress: string;
1554
+ queryMsg: object;
1555
+ enabled?: boolean;
1556
+ }) => {
1557
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1558
+
1559
+ return useGetSmartContractState({
1560
+ request: {
1561
+ address: contractAddress,
1562
+ queryData: new TextEncoder().encode(JSON.stringify(queryMsg)),
1563
+ },
1564
+ options: {
1565
+ enabled: !!contractAddress && !!queryMsg && !!rpcEndpoint && enabled,
1566
+ context: defaultContext,
1567
+ select: ({ data }) => {
1568
+ if (data) {
1569
+ return JSON.parse(new TextDecoder().decode(data));
1570
+ }
1571
+ return null;
1572
+ },
1573
+ },
1574
+ clientResolver: rpcEndpoint,
1575
+ });
1576
+ };
1577
+ `
1578
+ },
1579
+ {
1580
+ name: 'useCodeDetails.ts',
1581
+ content: `import { defaultContext } from '@tanstack/react-query';
1582
+ import { useGetCode } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1583
+
1584
+ export const useCodeDetails = ({
1585
+ codeId,
1586
+ enabled = true,
1587
+ }: {
1588
+ codeId: string | number;
1589
+ enabled?: boolean;
1590
+ }) => {
1591
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1592
+
1593
+ return useGetCode({
1594
+ request: {
1595
+ codeId: BigInt(codeId),
1596
+ },
1597
+ options: {
1598
+ enabled: !!codeId && !!rpcEndpoint && enabled,
1599
+ context: defaultContext,
1600
+ },
1601
+ clientResolver: rpcEndpoint,
1602
+ });
1603
+ };
1604
+ `
1605
+ },
1606
+ {
1607
+ name: 'useMyContracts.ts',
1608
+ content: `import { useMemo } from 'react';
1609
+ import { useChain } from '@interchain-kit/react';
1610
+ import { useGetContractsByCreator } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1611
+ import { defaultContext } from '@tanstack/react-query';
1612
+
1613
+ export const useMyContracts = (chainName: string) => {
1614
+ const { address } = useChain(chainName);
1615
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1616
+
1617
+ const contractsQuery = useGetContractsByCreator({
1618
+ request: {
1619
+ creatorAddress: address || '',
1620
+ pagination: {
1621
+ key: new Uint8Array(),
1622
+ offset: 0n,
1623
+ limit: 100n,
1624
+ countTotal: true,
1625
+ reverse: false,
1626
+ },
1627
+ },
1628
+ options: {
1629
+ enabled: !!address && !!rpcEndpoint,
1630
+ context: defaultContext,
1631
+ select: ({ contractAddresses }) => contractAddresses,
1632
+ },
1633
+ clientResolver: rpcEndpoint,
1634
+ });
1635
+
1636
+ const data = useMemo(() => {
1637
+ if (!contractsQuery.data) return;
1638
+
1639
+ return {
1640
+ contracts: contractsQuery.data.map((address) => ({
1641
+ address,
1642
+ label: \`Contract \${address.slice(0, 8)}...\`,
1643
+ })),
1644
+ count: contractsQuery.data.length,
1645
+ };
1646
+ }, [contractsQuery.data]);
1647
+
1648
+ return {
1649
+ data,
1650
+ isLoading: contractsQuery.isLoading,
1651
+ refetch: contractsQuery.refetch,
1652
+ };
1653
+ };
1654
+ `
1655
+ },
1656
+ {
1657
+ name: 'useGrants.ts',
1658
+ content: `import { useMemo } from 'react';
1659
+ import { useChain } from '@interchain-kit/react';
1660
+ import { useGetGranterGrants, useGetGranteeGrants } from '${packageName}/cosmos/authz/v1beta1/query.rpc.react';
1661
+ import { defaultContext } from '@tanstack/react-query';
1662
+
1663
+ export const useGrants = (chainName: string) => {
1664
+ const { address } = useChain(chainName);
1665
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1666
+
1667
+ const granterQuery = useGetGranterGrants({
1668
+ request: {
1669
+ granter: address || '',
1670
+ pagination: {
1671
+ key: new Uint8Array(),
1672
+ offset: 0n,
1673
+ limit: 100n,
1674
+ countTotal: true,
1675
+ reverse: false,
1676
+ },
1677
+ },
1678
+ options: {
1679
+ enabled: !!address && !!rpcEndpoint,
1680
+ context: defaultContext,
1681
+ select: ({ grants }) => grants,
1682
+ },
1683
+ clientResolver: rpcEndpoint,
1684
+ });
1685
+
1686
+ const granteeQuery = useGetGranteeGrants({
1687
+ request: {
1688
+ grantee: address || '',
1689
+ pagination: {
1690
+ key: new Uint8Array(),
1691
+ offset: 0n,
1692
+ limit: 100n,
1693
+ countTotal: true,
1694
+ reverse: false,
1695
+ },
1696
+ },
1697
+ options: {
1698
+ enabled: !!address && !!rpcEndpoint,
1699
+ context: defaultContext,
1700
+ select: ({ grants }) => grants,
1701
+ },
1702
+ clientResolver: rpcEndpoint,
1703
+ });
1704
+
1705
+ const data = useMemo(() => {
1706
+ return {
1707
+ granterGrants: granterQuery.data || [],
1708
+ granteeGrants: granteeQuery.data || [],
1709
+ };
1710
+ }, [granterQuery.data, granteeQuery.data]);
1711
+
1712
+ const isLoading = granterQuery.isLoading || granteeQuery.isLoading;
1713
+
1714
+ return {
1715
+ data,
1716
+ isLoading,
1717
+ refetch: () => {
1718
+ granterQuery.refetch();
1719
+ granteeQuery.refetch();
1720
+ },
1721
+ };
1722
+ };
1723
+ `
1724
+ },
1725
+ {
1726
+ name: 'useSendData.ts',
1727
+ content: `import { useMemo } from 'react';
1728
+ import { useChain } from '@interchain-kit/react';
1729
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1730
+ import { defaultContext } from '@tanstack/react-query';
1731
+ import BigNumber from 'bignumber.js';
1732
+
1733
+ export const useSendData = (chainName: string) => {
1734
+ const { address, assetList } = useChain(chainName);
1735
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1736
+
1737
+ const coin = assetList?.assets[0];
1738
+ const denom = coin?.base || 'uatom';
1739
+ const exponent = coin?.denomUnits?.find(unit => unit.denom === coin.display)?.exponent || 6;
1740
+
1741
+ const balanceQuery = useGetBalance({
1742
+ request: {
1743
+ address: address || '',
1744
+ denom,
1745
+ },
1746
+ options: {
1747
+ enabled: !!address && !!rpcEndpoint,
1748
+ context: defaultContext,
1749
+ select: ({ balance }) => {
1750
+ const amount = balance?.amount || '0';
1751
+ const displayAmount = new BigNumber(amount).dividedBy(Math.pow(10, exponent));
1752
+ return {
1753
+ amount,
1754
+ displayAmount: displayAmount.toString(),
1755
+ denom: balance?.denom || denom,
1756
+ };
1757
+ },
1758
+ },
1759
+ clientResolver: rpcEndpoint,
1760
+ });
1761
+
1762
+ const data = useMemo(() => {
1763
+ if (!balanceQuery.data) return;
1764
+
1765
+ return {
1766
+ balance: balanceQuery.data,
1767
+ canSend: new BigNumber(balanceQuery.data.amount).isGreaterThan(0),
1768
+ fee: {
1769
+ amount: '5000',
1770
+ displayAmount: new BigNumber('5000').dividedBy(Math.pow(10, exponent)).toString(),
1771
+ denom,
1772
+ },
1773
+ };
1774
+ }, [balanceQuery.data, denom, exponent]);
1775
+
1776
+ return {
1777
+ data,
1778
+ isLoading: balanceQuery.isLoading,
1779
+ refetch: balanceQuery.refetch,
1780
+ };
1781
+ };
1782
+ `
1783
+ },
1784
+ {
1785
+ name: 'useTotalAssets.ts',
1786
+ content: `import { useMemo } from 'react';
1787
+ import { useChain } from '@interchain-kit/react';
1788
+ import { useGetAllBalances } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1789
+ import { defaultContext } from '@tanstack/react-query';
1790
+ import BigNumber from 'bignumber.js';
1791
+
1792
+ export const getPagination = (limit: bigint) => ({
1793
+ key: new Uint8Array(),
1794
+ offset: 0n,
1795
+ limit,
1796
+ countTotal: true,
1797
+ reverse: false,
1798
+ });
1799
+
1800
+ export const useTotalAssets = (chainName: string) => {
1801
+ const { address, assetList } = useChain(chainName);
1802
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1803
+
1804
+ const allBalancesQuery = useGetAllBalances({
1805
+ request: {
1806
+ address: address || '',
1807
+ pagination: getPagination(100n),
1808
+ resolveDenom: false,
1809
+ },
1810
+ options: {
1811
+ enabled: !!address && !!rpcEndpoint,
1812
+ select: ({ balances }) => balances || [],
1813
+ context: defaultContext,
1814
+ },
1815
+ clientResolver: rpcEndpoint,
1816
+ customizedQueryKey: ['totalAssets', address],
1817
+ });
1818
+
1819
+ const data = useMemo(() => {
1820
+ if (!allBalancesQuery.data) return;
1821
+
1822
+ const totalValue = allBalancesQuery.data.reduce((sum, balance) => {
1823
+ return sum.plus(balance.amount);
1824
+ }, new BigNumber(0));
1825
+
1826
+ return {
1827
+ balances: allBalancesQuery.data,
1828
+ totalCount: allBalancesQuery.data.length,
1829
+ totalValue: totalValue.toString(),
1830
+ nonZeroBalances: allBalancesQuery.data.filter(
1831
+ balance => new BigNumber(balance.amount).isGreaterThan(0)
1832
+ ),
1833
+ };
1834
+ }, [allBalancesQuery.data]);
1835
+
1836
+ return {
1837
+ data,
1838
+ isLoading: allBalancesQuery.isLoading,
1839
+ refetch: allBalancesQuery.refetch,
1840
+ };
1841
+ };
1842
+ `
1843
+ }
1844
+ ];
1845
+ // Write all example files
1846
+ exampleFiles.forEach(({ name, content }) => {
1847
+ writeFileSync(join(mcpServerPath, 'src', 'telescope-examples', name), content);
1848
+ });
1849
+ }