@langwatch/mcp-server 2.1.0 → 3.0.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 (428) hide show
  1. package/.gitignore +7 -0
  2. package/.npmignore +41 -0
  3. package/CHANGELOG.md +218 -201
  4. package/CONTRIBUTING.md +10 -0
  5. package/README.md +70 -68
  6. package/dist/add-dashboard-widget-55UI6H22.js +44 -0
  7. package/dist/add-dashboard-widget-MJHIC3CC.js +45 -0
  8. package/dist/{archive-project-W3IKI7UL.js → archive-project-K5UD7A6X.js} +4 -4
  9. package/dist/archive-project-L4PAKT34.js +19 -0
  10. package/dist/{archive-run-plan-474OKHHU.js → archive-run-plan-5HSQG2HX.js} +4 -4
  11. package/dist/archive-run-plan-AOKNYQIO.js +15 -0
  12. package/dist/archive-scenario-2CWJW2VD.js +19 -0
  13. package/dist/{archive-scenario-V5UNYK26.js → archive-scenario-5IJQESHH.js} +4 -4
  14. package/dist/{archive-test-suite-O7FLDMXK.js → archive-test-suite-OPB7NFI7.js} +4 -4
  15. package/dist/archive-test-suite-ZC3TN6VH.js +15 -0
  16. package/dist/assign-prompt-tag-6DDE6ZZ5.js +23 -0
  17. package/dist/{assign-prompt-tag-Q46WRB6P.js → assign-prompt-tag-D7O23MJM.js} +8 -4
  18. package/dist/chunk-3YLN3ATJ.js +241 -0
  19. package/dist/{chunk-EYXMLE5X.js → chunk-4RX3G62A.js} +56 -47
  20. package/dist/{chunk-UF6XIGYR.js → chunk-6YZUOD34.js} +2 -5
  21. package/dist/{chunk-WVI5CJ6S.js → chunk-7AQLPVFL.js} +2 -2
  22. package/dist/chunk-7CZQDZ2K.js +319 -0
  23. package/dist/{chunk-RVAE2MEA.js → chunk-7GETGE6B.js} +7 -7
  24. package/dist/{chunk-OJLYYJWI.js → chunk-AASW2TO2.js} +7 -10
  25. package/dist/{chunk-QAMP3CGR.js → chunk-B4RFWIUP.js} +4 -4
  26. package/dist/{chunk-ZXKLPC2E.js → chunk-BIIKE3EI.js} +1 -1
  27. package/dist/{chunk-G4ZAZTZW.js → chunk-D2HS73VI.js} +7 -10
  28. package/dist/{chunk-37SMPMQS.js → chunk-DMM3JQ42.js} +7 -2
  29. package/dist/{chunk-WT4PO4A3.js → chunk-DULFP3MK.js} +10 -7
  30. package/dist/chunk-EYPJBL7P.js +516 -0
  31. package/dist/{chunk-NUFPTHKU.js → chunk-FOKVY3BK.js} +1 -1
  32. package/dist/chunk-GA5JUSPT.js +64 -0
  33. package/dist/{chunk-UJPXFA26.js → chunk-HHMNZAPD.js} +101 -74
  34. package/dist/chunk-HLQJXUR6.js +67 -0
  35. package/dist/{chunk-JTQJRNFJ.js → chunk-KILVK3FS.js} +4 -4
  36. package/dist/chunk-MOCU5XWF.js +79 -0
  37. package/dist/chunk-O2WGVCED.js +41 -0
  38. package/dist/{chunk-HV4DWKBI.js → chunk-O7EMWEVJ.js} +2 -4
  39. package/dist/{chunk-UFOYFYI7.js → chunk-QXLMHLRC.js} +6 -9
  40. package/dist/{chunk-QRO35SOM.js → chunk-R5YJIYPF.js} +981 -747
  41. package/dist/{chunk-JR6DJZOU.js → chunk-RABYBFX5.js} +4 -10
  42. package/dist/{chunk-SR6QPRIE.js → chunk-RFC2SBEX.js} +7 -13
  43. package/dist/chunk-SHSVN3SE.js +21 -0
  44. package/dist/{chunk-CKNAH5TG.js → chunk-U24EACC4.js} +3 -10
  45. package/dist/{chunk-56OGTS24.js → chunk-VOUGDY2O.js} +4 -11
  46. package/dist/chunk-WCKZDOGF.js +31 -0
  47. package/dist/chunk-XQYH52SI.js +129 -0
  48. package/dist/{chunk-7E4FZIYJ.js → chunk-XUIJYNRJ.js} +1 -1
  49. package/dist/{chunk-6DJDEXET.js → chunk-YCIUEZVK.js} +6 -12
  50. package/dist/config-2WQGMAEN.js +16 -0
  51. package/dist/config.cjs +109 -0
  52. package/dist/config.js +5 -4
  53. package/dist/{create-agent-JFJ2K6X3.js → create-agent-6JNLMYQD.js} +4 -4
  54. package/dist/create-agent-IRZOU4R5.js +23 -0
  55. package/dist/create-analytics-report-N4L4V5QL.js +19 -0
  56. package/dist/create-analytics-report-QEHXG7FU.js +18 -0
  57. package/dist/{create-annotation-EUXXQ6NS.js → create-annotation-CCEGIZ67.js} +10 -5
  58. package/dist/create-annotation-DTHCMWHB.js +29 -0
  59. package/dist/{create-api-key-BGBB76JX.js → create-api-key-JKM2DSZO.js} +5 -7
  60. package/dist/create-api-key-JPEUIXGM.js +24 -0
  61. package/dist/create-dataset-DJNXYJ5B.js +22 -0
  62. package/dist/{create-dataset-FD5VAXU4.js → create-dataset-WON4SOTC.js} +6 -6
  63. package/dist/create-dataset-records-TMEOTLTO.js +20 -0
  64. package/dist/{create-dataset-records-WQUXXOHI.js → create-dataset-records-UJBW3C7C.js} +5 -7
  65. package/dist/create-evaluator-N5AEHI4K.js +27 -0
  66. package/dist/{create-evaluator-6NV33Z52.js → create-evaluator-XYNY2YFY.js} +4 -4
  67. package/dist/create-mcp-server.cjs +9712 -0
  68. package/dist/create-mcp-server.js +2757 -10
  69. package/dist/{create-project-ZQ7TFIO2.js → create-project-EY4XZ7TH.js} +4 -4
  70. package/dist/create-project-YL345T5L.js +44 -0
  71. package/dist/{create-prompt-BS6QRCUU.js → create-prompt-JZQNQ7I3.js} +5 -7
  72. package/dist/create-prompt-ZUMQHHX7.js +37 -0
  73. package/dist/create-prompt-tag-CJ5FZ436.js +17 -0
  74. package/dist/{create-prompt-tag-FCQ5ELSQ.js → create-prompt-tag-JFP2Q3PO.js} +3 -3
  75. package/dist/create-scenario-CQU2SSFB.js +33 -0
  76. package/dist/{create-scenario-DRPTPXU3.js → create-scenario-S6OWWKJO.js} +5 -5
  77. package/dist/create-test-suite-OLGCAGJA.js +36 -0
  78. package/dist/{create-test-suite-ZIZCCFJ4.js → create-test-suite-Y7P2RI4L.js} +6 -6
  79. package/dist/create-trigger-4CNBTISJ.js +48 -0
  80. package/dist/create-trigger-RQ653WYF.js +49 -0
  81. package/dist/dashboards-BA7M6CMO.js +90 -0
  82. package/dist/dashboards-U663GUIB.js +91 -0
  83. package/dist/{delete-agent-SA4JMUZF.js → delete-agent-J2Q4DRZ2.js} +4 -4
  84. package/dist/delete-agent-ZAU4LTXB.js +18 -0
  85. package/dist/delete-analytics-report-QK6X7P4S.js +19 -0
  86. package/dist/delete-analytics-report-YUYLDHLL.js +18 -0
  87. package/dist/delete-annotation-7X4NYXXM.js +17 -0
  88. package/dist/{delete-annotation-X3KKK7QY.js → delete-annotation-KJOCDLV3.js} +4 -4
  89. package/dist/{delete-dataset-W6EZ44HY.js → delete-dataset-NXP7ZPPV.js} +5 -7
  90. package/dist/delete-dataset-RUTZBBVD.js +18 -0
  91. package/dist/{delete-dataset-records-7CNOTALB.js → delete-dataset-records-4Z7DZCDW.js} +5 -7
  92. package/dist/delete-dataset-records-75UAR5IS.js +19 -0
  93. package/dist/delete-evaluator-E3CUNGTQ.js +16 -0
  94. package/dist/delete-evaluator-RI4GALGX.js +15 -0
  95. package/dist/delete-prompt-tag-LE3WJPKS.js +17 -0
  96. package/dist/{delete-prompt-tag-QB3OCZUV.js → delete-prompt-tag-S4KBZTNG.js} +3 -3
  97. package/dist/delete-workflow-4CZFIQCQ.js +17 -0
  98. package/dist/{delete-workflow-NG2VXYYM.js → delete-workflow-PWQPDW6H.js} +4 -4
  99. package/dist/discover-evaluator-schema-UHWA5HVL.js +120 -0
  100. package/dist/discover-evaluator-schema-XKCLLCB3.js +118 -0
  101. package/dist/discover-scenario-schema-NOJY6S7E.js +137 -0
  102. package/dist/{discover-scenario-schema-W7KBXA4J.js → discover-scenario-schema-OOFIQKOG.js} +37 -17
  103. package/dist/discover-schema-7WHIIATI.js +442 -0
  104. package/dist/{discover-schema-L6QDPON3.js → discover-schema-J2ANOBKO.js} +181 -186
  105. package/dist/get-agent-5T3CXQOR.js +69 -0
  106. package/dist/{get-agent-7THF7HCU.js → get-agent-ZKYQJUQ7.js} +15 -11
  107. package/dist/get-analytics-4MPEK4KV.js +79 -0
  108. package/dist/get-analytics-ZLI3A4F5.js +80 -0
  109. package/dist/get-analytics-report-JCKYMA2S.js +29 -0
  110. package/dist/get-analytics-report-SKIP2JWH.js +30 -0
  111. package/dist/get-dataset-APGZBYMH.js +64 -0
  112. package/dist/get-dataset-LWXDVMVE.js +63 -0
  113. package/dist/get-evaluator-3A7BJBAB.js +47 -0
  114. package/dist/{get-evaluator-RZ44UIN6.js → get-evaluator-IWNJINRY.js} +4 -4
  115. package/dist/get-project-EQVB4LEL.js +26 -0
  116. package/dist/{get-project-QSQEAB33.js → get-project-RK6AJTEP.js} +4 -4
  117. package/dist/{get-prompt-GVKXF5NL.js → get-prompt-TLG2T2DS.js} +53 -58
  118. package/dist/get-prompt-ZER557X3.js +94 -0
  119. package/dist/get-run-plan-5X7DDJRN.js +58 -0
  120. package/dist/{get-run-plan-NY7J5GRE.js → get-run-plan-PEHRO5M3.js} +7 -9
  121. package/dist/{get-scenario-Q3LLQE4T.js → get-scenario-375W5D6I.js} +5 -5
  122. package/dist/get-scenario-UQX45ZZO.js +37 -0
  123. package/dist/{get-simulation-run-WINEYDMK.js → get-simulation-run-2NBXJADG.js} +26 -22
  124. package/dist/get-simulation-run-QZTLGL7W.js +69 -0
  125. package/dist/{get-test-suite-4HKA7OKS.js → get-test-suite-GVIBDG7K.js} +5 -5
  126. package/dist/get-test-suite-OODIR3RI.js +48 -0
  127. package/dist/{get-trace-RCUV7N4O.js → get-trace-AGCHVPJK.js} +11 -13
  128. package/dist/get-trace-KJLYAZRC.js +45 -0
  129. package/dist/get-workflow-3TV2YYC5.js +25 -0
  130. package/dist/{get-workflow-EEOC7Y45.js → get-workflow-7LZSVPP2.js} +4 -4
  131. package/dist/{http-security-EU3CHTY7.js → http-security-DNLBNQZL.js} +2 -2
  132. package/dist/{http-server-WCDUARTH.js → http-server-7CCN3EHJ.js} +4249 -325
  133. package/dist/index.js +59595 -38027
  134. package/dist/langwatch-api-analytics-reports-6CF6KUET.js +17 -0
  135. package/dist/langwatch-api-analytics-reports-RPFB5AO5.js +18 -0
  136. package/dist/{langwatch-api-annotations-6DHVZWUK.js → langwatch-api-annotations-H4AI4TKG.js} +4 -4
  137. package/dist/langwatch-api-annotations-QSJNUQQS.js +17 -0
  138. package/dist/langwatch-api-monitors-ENHLOL3S.js +47 -0
  139. package/dist/{langwatch-api-monitors-6ISFJ7WX.js → langwatch-api-monitors-OHSGADTH.js} +11 -16
  140. package/dist/langwatch-api-secrets-AGW6UUMD.js +55 -0
  141. package/dist/langwatch-api-secrets-CLTS766Q.js +56 -0
  142. package/dist/langwatch-api-triggers-G5UWFNN2.js +22 -0
  143. package/dist/langwatch-api-triggers-QMR7KEXW.js +23 -0
  144. package/dist/langwatch-api-workflows-HKTBIKKY.js +15 -0
  145. package/dist/{langwatch-api-workflows-6UJL5U4Z.js → langwatch-api-workflows-OMROZH2O.js} +4 -4
  146. package/dist/{list-agents-AMVDQPQL.js → list-agents-BYWDNAHT.js} +4 -4
  147. package/dist/list-agents-MG24MHZE.js +42 -0
  148. package/dist/list-analytics-reports-G3EPWGSQ.js +32 -0
  149. package/dist/list-analytics-reports-PPWIFRES.js +33 -0
  150. package/dist/list-annotations-QCLGEK5A.js +38 -0
  151. package/dist/{list-annotations-6PR5NLIC.js → list-annotations-Y4EUBJHG.js} +10 -5
  152. package/dist/list-api-keys-DAVOBPFK.js +42 -0
  153. package/dist/{list-api-keys-GVPNBIHQ.js → list-api-keys-JMW5WRXX.js} +10 -5
  154. package/dist/list-dashboards-2P3VJFRS.js +29 -0
  155. package/dist/list-dashboards-MW5O3MKH.js +30 -0
  156. package/dist/list-dataset-records-KEHT7G6Q.js +43 -0
  157. package/dist/{list-dataset-records-O67HZ35Y.js → list-dataset-records-KMLLMZAZ.js} +14 -10
  158. package/dist/{list-datasets-WXZL6UMP.js → list-datasets-P3JK2ZHS.js} +9 -13
  159. package/dist/list-datasets-Z7OOE4KI.js +56 -0
  160. package/dist/{list-evaluators-PAX72WCN.js → list-evaluators-7RRESBOU.js} +5 -7
  161. package/dist/list-evaluators-VATJVOHR.js +32 -0
  162. package/dist/{list-model-providers-VVLZMLCX.js → list-model-providers-OXDRPUCJ.js} +4 -4
  163. package/dist/list-model-providers-VXQJWDXU.js +35 -0
  164. package/dist/{list-projects-AQVI6SUK.js → list-projects-HUVK7L3W.js} +5 -7
  165. package/dist/list-projects-X72ZXVY5.js +40 -0
  166. package/dist/{list-prompt-tags-WZFBJOHG.js → list-prompt-tags-3I3LWFIR.js} +3 -3
  167. package/dist/list-prompt-tags-DRHUH2ND.js +23 -0
  168. package/dist/list-prompts-6DX3QECJ.js +30 -0
  169. package/dist/{list-prompts-BQOHRHYT.js → list-prompts-PS423RU3.js} +4 -6
  170. package/dist/list-run-plans-5SXPOV3X.js +45 -0
  171. package/dist/{list-run-plans-UBAU2DGH.js → list-run-plans-6VNHINPY.js} +5 -5
  172. package/dist/list-scenarios-EQWCW7Q4.js +45 -0
  173. package/dist/{list-scenarios-MS4IUIVM.js → list-scenarios-GKNH3YND.js} +13 -11
  174. package/dist/{list-simulation-runs-D6YF4ZOU.js → list-simulation-runs-KHY7KALI.js} +12 -8
  175. package/dist/list-simulation-runs-PUDK32C2.js +53 -0
  176. package/dist/list-test-suites-7H2DRILK.js +34 -0
  177. package/dist/{list-test-suites-L7R2O6DR.js → list-test-suites-GY56LGLY.js} +4 -4
  178. package/dist/list-trigger-fires-7RZUP54Y.js +19 -0
  179. package/dist/list-trigger-fires-OZUF65LI.js +20 -0
  180. package/dist/list-triggers-BGUCUXTJ.js +45 -0
  181. package/dist/list-triggers-XC5KMX4C.js +46 -0
  182. package/dist/list-workflows-55NYC3PC.js +33 -0
  183. package/dist/{list-workflows-6MV4XJHF.js → list-workflows-HV7FUWZA.js} +5 -7
  184. package/dist/{rename-prompt-tag-K5LQ4CY6.js → rename-prompt-tag-2I7Z5FCY.js} +3 -3
  185. package/dist/rename-prompt-tag-SZYTOWDX.js +18 -0
  186. package/dist/{rename-test-suite-NTYHAO5X.js → rename-test-suite-27AYY33K.js} +4 -4
  187. package/dist/rename-test-suite-CLIEPZDO.js +20 -0
  188. package/dist/report-issue-5HSL7CNB.js +924 -0
  189. package/dist/{report-issue-RHZZ33IS.js → report-issue-N7ND5TM6.js} +107 -67
  190. package/dist/{rerun-run-plan-MUDWJBE4.js → rerun-run-plan-O3VUZ6CG.js} +5 -5
  191. package/dist/rerun-run-plan-OJTVVGJI.js +21 -0
  192. package/dist/{revoke-api-key-6LAZ3QZZ.js → revoke-api-key-BU6BKGCG.js} +4 -4
  193. package/dist/revoke-api-key-NZNCFOIR.js +15 -0
  194. package/dist/run-agent-244O4Y5M.js +75 -0
  195. package/dist/run-agent-HPCGZGYW.js +74 -0
  196. package/dist/run-plan-2ZPGGZ4H.js +38 -0
  197. package/dist/{run-plan-T4ZYOZGA.js → run-plan-KSXUYQT3.js} +7 -7
  198. package/dist/run-query-4LMOQ5UW.js +47 -0
  199. package/dist/run-query-BQUHIUC2.js +46 -0
  200. package/dist/{run-test-suite-L4MZ7G4D.js → run-test-suite-P3WLVPXC.js} +6 -6
  201. package/dist/run-test-suite-UEOMCON6.js +25 -0
  202. package/dist/run-workflow-EFZ6HG5B.js +36 -0
  203. package/dist/{run-workflow-DFIS23AP.js → run-workflow-I4IHEN54.js} +4 -4
  204. package/dist/search-traces-6IR7PR4L.js +170 -0
  205. package/dist/search-traces-BYML2NQ4.js +171 -0
  206. package/dist/set-model-provider-RBNGWFVI.js +33 -0
  207. package/dist/{set-model-provider-XRNMFOVR.js → set-model-provider-SHEVKWRC.js} +4 -4
  208. package/dist/{update-agent-DUWNYBNA.js → update-agent-PTKTM2B5.js} +4 -4
  209. package/dist/update-agent-ZPXWRMS2.js +20 -0
  210. package/dist/update-dashboard-widget-HKCBXH7X.js +62 -0
  211. package/dist/update-dashboard-widget-IP2TTQ5G.js +63 -0
  212. package/dist/update-dataset-GHIN6JR3.js +22 -0
  213. package/dist/{update-dataset-YSOMDCOB.js → update-dataset-IRVMY5PF.js} +6 -6
  214. package/dist/update-dataset-record-6VI7K2CL.js +19 -0
  215. package/dist/{update-dataset-record-DEA2ITYR.js → update-dataset-record-Z3L7ACNF.js} +4 -4
  216. package/dist/update-evaluator-5NLNE6VY.js +24 -0
  217. package/dist/{update-evaluator-NH7Q5GWV.js → update-evaluator-FEH7H6NS.js} +4 -4
  218. package/dist/update-project-75H3LDQT.js +24 -0
  219. package/dist/{update-project-Q26FBSYH.js → update-project-QPR3QX55.js} +4 -4
  220. package/dist/update-prompt-BCDFTNLK.js +140 -0
  221. package/dist/{update-prompt-ZQQ2C3KU.js → update-prompt-NPRXYSWA.js} +27 -29
  222. package/dist/update-scenario-BNOMDCMV.js +34 -0
  223. package/dist/{update-scenario-WUX34JAR.js → update-scenario-EM5XGMB7.js} +5 -5
  224. package/package.json +35 -39
  225. package/pyproject.toml +23 -8
  226. package/src/config.d.ts +6 -0
  227. package/src/config.ts +22 -29
  228. package/src/create-mcp-server.ts +887 -634
  229. package/src/documentation-fetch.ts +21 -20
  230. package/src/http-security.ts +166 -135
  231. package/src/http-server.ts +189 -224
  232. package/src/index.ts +14 -16
  233. package/src/langwatch-api-agents.ts +18 -21
  234. package/src/langwatch-api-analytics-reports.ts +62 -0
  235. package/src/langwatch-api-annotations.ts +11 -12
  236. package/src/langwatch-api-api-keys.ts +8 -9
  237. package/src/langwatch-api-dashboard-widgets.ts +47 -0
  238. package/src/langwatch-api-dashboards.ts +109 -24
  239. package/src/langwatch-api-datasets.ts +98 -32
  240. package/src/langwatch-api-evaluators.ts +13 -19
  241. package/src/langwatch-api-model-providers.ts +4 -4
  242. package/src/langwatch-api-monitors.ts +14 -18
  243. package/src/langwatch-api-projects.ts +10 -9
  244. package/src/langwatch-api-query.ts +114 -0
  245. package/src/langwatch-api-run-plans.ts +12 -29
  246. package/src/langwatch-api-scenarios.ts +9 -11
  247. package/src/langwatch-api-secrets.ts +31 -24
  248. package/src/langwatch-api-simulation-runs.ts +6 -8
  249. package/src/langwatch-api-test-suites.ts +14 -33
  250. package/src/langwatch-api-triggers.ts +96 -34
  251. package/src/langwatch-api-workflows.ts +9 -9
  252. package/src/langwatch-api.ts +118 -124
  253. package/src/public-http-request.ts +21 -12
  254. package/src/schemas/analytics-metrics.ts +3 -15
  255. package/src/schemas/create-dataset.ts +3 -4
  256. package/src/schemas/run-plan.ts +13 -29
  257. package/src/schemas/suite-fields.ts +6 -23
  258. package/src/schemas/triggers.ts +365 -0
  259. package/src/schemas/widget-sources.ts +33 -0
  260. package/src/tools/add-dashboard-widget.ts +51 -0
  261. package/src/tools/archive-project.ts +2 -4
  262. package/src/tools/archive-run-plan.ts +2 -4
  263. package/src/tools/archive-scenario.ts +2 -4
  264. package/src/tools/archive-test-suite.ts +2 -4
  265. package/src/tools/assign-prompt-tag.ts +6 -2
  266. package/src/tools/create-agent.ts +1 -1
  267. package/src/tools/create-analytics-report.ts +7 -0
  268. package/src/tools/create-annotation.ts +7 -2
  269. package/src/tools/create-api-key.ts +4 -6
  270. package/src/tools/create-dataset-records.ts +4 -8
  271. package/src/tools/create-dataset.ts +5 -7
  272. package/src/tools/create-evaluator.ts +3 -5
  273. package/src/tools/create-project.ts +2 -2
  274. package/src/tools/create-prompt-tag.ts +2 -4
  275. package/src/tools/create-prompt.ts +9 -18
  276. package/src/tools/create-scenario.ts +5 -7
  277. package/src/tools/create-test-suite.ts +4 -9
  278. package/src/tools/create-trigger.ts +55 -0
  279. package/src/tools/dashboard-widget-queries.ts +45 -0
  280. package/src/tools/dashboards.ts +104 -0
  281. package/src/tools/delete-agent.ts +1 -1
  282. package/src/tools/delete-analytics-report.ts +7 -0
  283. package/src/tools/delete-annotation.ts +1 -1
  284. package/src/tools/delete-dataset-records.ts +4 -8
  285. package/src/tools/delete-dataset.ts +3 -7
  286. package/src/tools/delete-evaluator.ts +4 -6
  287. package/src/tools/delete-prompt-tag.ts +2 -4
  288. package/src/tools/delete-workflow.ts +1 -1
  289. package/src/tools/discover-evaluator-schema.ts +34 -25
  290. package/src/tools/discover-scenario-schema.ts +41 -21
  291. package/src/tools/discover-schema.ts +149 -27
  292. package/src/tools/experiment-run-status.ts +2 -8
  293. package/src/tools/format-dataset-mutation.ts +5 -10
  294. package/src/tools/format-run-plan.ts +7 -21
  295. package/src/tools/format-scenario.ts +2 -4
  296. package/src/tools/format-suite-details.ts +6 -12
  297. package/src/tools/get-agent.ts +15 -6
  298. package/src/tools/get-analytics-report.ts +23 -0
  299. package/src/tools/get-analytics.ts +52 -46
  300. package/src/tools/get-dataset.ts +34 -16
  301. package/src/tools/get-evaluator.ts +4 -11
  302. package/src/tools/get-experiment-results.ts +219 -186
  303. package/src/tools/get-project.ts +2 -4
  304. package/src/tools/get-prompt.ts +63 -84
  305. package/src/tools/get-run-plan.ts +4 -6
  306. package/src/tools/get-scenario.ts +4 -6
  307. package/src/tools/get-simulation-run.ts +27 -24
  308. package/src/tools/get-test-suite.ts +2 -5
  309. package/src/tools/get-trace.ts +16 -17
  310. package/src/tools/get-workflow.ts +1 -1
  311. package/src/tools/list-agents.ts +1 -1
  312. package/src/tools/list-analytics-reports.ts +27 -0
  313. package/src/tools/list-annotations.ts +8 -5
  314. package/src/tools/list-api-keys.ts +7 -2
  315. package/src/tools/list-dashboards.ts +20 -21
  316. package/src/tools/list-dataset-records.ts +8 -6
  317. package/src/tools/list-datasets.ts +12 -23
  318. package/src/tools/list-evaluators.ts +4 -8
  319. package/src/tools/list-experiment-runs.ts +5 -9
  320. package/src/tools/list-experiments.ts +5 -11
  321. package/src/tools/list-model-providers.ts +3 -5
  322. package/src/tools/list-projects.ts +2 -4
  323. package/src/tools/list-prompt-tags.ts +3 -3
  324. package/src/tools/list-prompts.ts +4 -8
  325. package/src/tools/list-run-plans.ts +2 -2
  326. package/src/tools/list-scenarios.ts +14 -15
  327. package/src/tools/list-simulation-runs.ts +8 -4
  328. package/src/tools/list-test-suites.ts +1 -1
  329. package/src/tools/list-trigger-fires.ts +17 -0
  330. package/src/tools/list-triggers.ts +39 -0
  331. package/src/tools/list-workflows.ts +2 -4
  332. package/src/tools/rename-prompt-tag.ts +1 -1
  333. package/src/tools/rename-test-suite.ts +2 -5
  334. package/src/tools/report-issue.ts +7 -9
  335. package/src/tools/rerun-run-plan.ts +2 -5
  336. package/src/tools/revoke-api-key.ts +2 -4
  337. package/src/tools/run-agent.ts +29 -26
  338. package/src/tools/run-experiment.ts +37 -34
  339. package/src/tools/run-plan.ts +4 -7
  340. package/src/tools/run-query.ts +47 -0
  341. package/src/tools/run-test-suite.ts +4 -7
  342. package/src/tools/run-workflow.ts +2 -5
  343. package/src/tools/search-traces.ts +161 -47
  344. package/src/tools/set-model-provider.ts +4 -6
  345. package/src/tools/test-agent.ts +2 -2
  346. package/src/tools/update-agent.ts +1 -1
  347. package/src/tools/update-dashboard-widget.ts +86 -0
  348. package/src/tools/update-dataset-record.ts +1 -1
  349. package/src/tools/update-dataset.ts +5 -7
  350. package/src/tools/update-evaluator.ts +3 -5
  351. package/src/tools/update-project.ts +1 -1
  352. package/src/tools/update-prompt.ts +44 -59
  353. package/src/tools/update-scenario.ts +5 -7
  354. package/src/tools/update-test-suite.ts +6 -11
  355. package/src/utils/date-parsing.ts +1 -1
  356. package/src/utils/escape-markdown.ts +3 -8
  357. package/src/utils/format-evaluations.ts +6 -6
  358. package/src/utils/markdown-table.ts +58 -0
  359. package/src/utils/trace-id-shape.ts +20 -0
  360. package/tsconfig.app.json +24 -0
  361. package/tsconfig.json +14 -12
  362. package/uv.lock +667 -341
  363. package/vitest.integration.config.js +10 -0
  364. package/vitest.scenario.config.js +9 -0
  365. package/.eslintrc.cjs +0 -36
  366. package/dist/chunk-AN4OUA4D.js +0 -86
  367. package/dist/chunk-GELJ2MQR.js +0 -226
  368. package/dist/chunk-K37ZNPXK.js +0 -24
  369. package/dist/chunk-S4GVX36W.js +0 -39
  370. package/dist/config.d.ts +0 -17
  371. package/dist/create-dashboard-Z76AIPLS.js +0 -19
  372. package/dist/create-mcp-server.d.ts +0 -10
  373. package/dist/delete-dashboard-LYMRPF27.js +0 -19
  374. package/dist/delete-evaluator-RKYC4TNB.js +0 -16
  375. package/dist/discover-evaluator-schema-ESSHQGPY.js +0 -1912
  376. package/dist/get-analytics-R6AZD3AW.js +0 -73
  377. package/dist/get-dashboard-P4WWVHFU.js +0 -30
  378. package/dist/get-dataset-AKTYSQDI.js +0 -49
  379. package/dist/index.d.ts +0 -2
  380. package/dist/langwatch-api-dashboards-2KJL2M42.js +0 -18
  381. package/dist/langwatch-api-secrets-OEBD6GBU.js +0 -41
  382. package/dist/langwatch-api-triggers-5E6DDGX6.js +0 -31
  383. package/dist/list-dashboards-Z3BZKDGF.js +0 -33
  384. package/dist/run-agent-CAGWGTYT.js +0 -72
  385. package/dist/search-traces-4XTJYXIK.js +0 -79
  386. package/src/__tests__/agent-tools.unit.test.ts +0 -257
  387. package/src/__tests__/all-tools.integration.test.ts +0 -1872
  388. package/src/__tests__/config.unit.test.ts +0 -202
  389. package/src/__tests__/datasets.integration.test.ts +0 -620
  390. package/src/__tests__/datasets.unit.test.ts +0 -244
  391. package/src/__tests__/date-parsing.unit.test.ts +0 -78
  392. package/src/__tests__/discover-evaluator-schema.unit.test.ts +0 -89
  393. package/src/__tests__/discover-schema.unit.test.ts +0 -118
  394. package/src/__tests__/docker.integration.test.ts +0 -318
  395. package/src/__tests__/documentation-fetch-security.integration.test.ts +0 -182
  396. package/src/__tests__/evaluator-tools.unit.test.ts +0 -262
  397. package/src/__tests__/experiment-list-tools.unit.test.ts +0 -157
  398. package/src/__tests__/experiment-status.unit.test.ts +0 -194
  399. package/src/__tests__/feature-map-tool-drift.unit.test.ts +0 -93
  400. package/src/__tests__/get-experiment-results.unit.test.ts +0 -313
  401. package/src/__tests__/http-security-origin.unit.test.ts +0 -97
  402. package/src/__tests__/http-security-sessions.unit.test.ts +0 -209
  403. package/src/__tests__/http-security-verifier.unit.test.ts +0 -248
  404. package/src/__tests__/http-server-allocation.integration.test.ts +0 -279
  405. package/src/__tests__/http-server-origin.integration.test.ts +0 -169
  406. package/src/__tests__/http-server-session-auth.integration.test.ts +0 -341
  407. package/src/__tests__/http-transport.integration.test.ts +0 -395
  408. package/src/__tests__/integration.integration.test.ts +0 -284
  409. package/src/__tests__/langwatch-api.unit.test.ts +0 -661
  410. package/src/__tests__/model-provider-tools.unit.test.ts +0 -190
  411. package/src/__tests__/project-api-key-tools.unit.test.ts +0 -451
  412. package/src/__tests__/prompt-response-types.unit.test.ts +0 -51
  413. package/src/__tests__/prompts.integration.test.ts +0 -736
  414. package/src/__tests__/public-http-request-security.integration.test.ts +0 -118
  415. package/src/__tests__/report-issue.integration.test.ts +0 -147
  416. package/src/__tests__/run-plan-tools.unit.test.ts +0 -565
  417. package/src/__tests__/scenario-tools.integration.test.ts +0 -286
  418. package/src/__tests__/scenario-tools.unit.test.ts +0 -207
  419. package/src/__tests__/schemas.unit.test.ts +0 -85
  420. package/src/__tests__/simulation-run-tools.unit.test.ts +0 -116
  421. package/src/__tests__/support/http-server-harness.ts +0 -138
  422. package/src/__tests__/test-suite-tools.unit.test.ts +0 -615
  423. package/src/__tests__/tools.integration.test.ts +0 -896
  424. package/src/schemas/filter-fields.ts +0 -119
  425. package/src/schemas/index.ts +0 -9
  426. package/src/tools/create-dashboard.ts +0 -7
  427. package/src/tools/delete-dashboard.ts +0 -7
  428. package/src/tools/get-dashboard.ts +0 -22
@@ -1,395 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, it } from "vitest";
2
- import { initConfig } from "../config.js";
3
- import type { ApiKeyVerifier } from "../http-security.js";
4
- import type { Server } from "http";
5
-
6
- /** Standard headers required by the MCP Streamable HTTP protocol for POST requests */
7
- const MCP_POST_HEADERS = {
8
- "Content-Type": "application/json",
9
- Accept: "application/json, text/event-stream",
10
- };
11
-
12
- const BEARER_TOKEN = "test-session-key";
13
-
14
- /**
15
- * Stands in for the LangWatch API. The standalone server has no database, so
16
- * it asks the API whether a key is real; here one key is.
17
- */
18
- function stubVerifier(validKeys: string[]): ApiKeyVerifier {
19
- return {
20
- verify: async (apiKey: string) => validKeys.includes(apiKey),
21
- sweep: () => undefined,
22
- clear: () => undefined,
23
- };
24
- }
25
-
26
- /** Helper to create auth + MCP headers */
27
- function mcpHeaders({
28
- sessionId,
29
- apiKey,
30
- }: { sessionId?: string; apiKey?: string } = {}) {
31
- const headers: Record<string, string> = {
32
- ...MCP_POST_HEADERS,
33
- Authorization: `Bearer ${apiKey ?? BEARER_TOKEN}`,
34
- };
35
- if (sessionId) {
36
- headers["mcp-session-id"] = sessionId;
37
- }
38
- return headers;
39
- }
40
-
41
- function initializeBody() {
42
- return JSON.stringify({
43
- jsonrpc: "2.0",
44
- method: "initialize",
45
- params: {
46
- protocolVersion: "2025-03-26",
47
- capabilities: {},
48
- clientInfo: { name: "test-client", version: "1.0.0" },
49
- },
50
- id: 1,
51
- });
52
- }
53
-
54
- describe("HTTP transport", () => {
55
- let httpServer: Server;
56
- let port: number;
57
- let baseUrl: string;
58
-
59
- beforeAll(async () => {
60
- // Initialize with no API key -- HTTP mode relies on per-session Bearer tokens
61
- initConfig({
62
- endpoint: "https://app.langwatch.ai",
63
- });
64
-
65
- const { startHttpServer } = await import("../http-server.js");
66
- const result = await startHttpServer({
67
- port: 0,
68
- apiKeyVerifier: stubVerifier([BEARER_TOKEN, "my-langwatch-api-key"]),
69
- });
70
- httpServer = result.server;
71
- port = result.port;
72
- baseUrl = `http://127.0.0.1:${port}`;
73
- });
74
-
75
- afterAll(async () => {
76
- await new Promise<void>((resolve) => {
77
- httpServer.close(() => resolve());
78
- });
79
- });
80
-
81
- describe("/health endpoint", () => {
82
- it("returns ok status without authentication", async () => {
83
- const response = await fetch(`${baseUrl}/health`);
84
- const body = await response.json();
85
-
86
- expect(response.status).toBe(200);
87
- expect(body).toEqual({ status: "ok" });
88
- });
89
- });
90
-
91
- describe("CORS headers", () => {
92
- it("sends no Access-Control-Allow-Origin when the request has no Origin", async () => {
93
- const response = await fetch(`${baseUrl}/health`);
94
-
95
- expect(response.status).toBe(200);
96
- expect(response.headers.get("access-control-allow-origin")).toBeNull();
97
- });
98
-
99
- it("reflects an allowed origin rather than answering with a wildcard", async () => {
100
- const response = await fetch(`${baseUrl}/health`, {
101
- headers: { Origin: "http://localhost:5173" },
102
- });
103
-
104
- expect(response.headers.get("access-control-allow-origin")).toBe(
105
- "http://localhost:5173"
106
- );
107
- expect(response.headers.get("vary")).toContain("Origin");
108
- });
109
-
110
- it("responds to OPTIONS preflight requests", async () => {
111
- const response = await fetch(`${baseUrl}/mcp`, {
112
- method: "OPTIONS",
113
- });
114
-
115
- expect(response.status).toBe(204);
116
- expect(response.headers.get("access-control-allow-methods")).toContain(
117
- "POST"
118
- );
119
- expect(response.headers.get("access-control-allow-headers")).toContain(
120
- "mcp-session-id"
121
- );
122
- });
123
-
124
- it("includes Authorization in allowed headers for CORS", async () => {
125
- const response = await fetch(`${baseUrl}/mcp`, {
126
- method: "OPTIONS",
127
- });
128
-
129
- expect(response.headers.get("access-control-allow-headers")).toContain(
130
- "Authorization"
131
- );
132
- });
133
- });
134
-
135
- describe("/mcp endpoint (Streamable HTTP)", () => {
136
- describe("when no Bearer token is provided", () => {
137
- it("returns 401 on initialize request", async () => {
138
- const response = await fetch(`${baseUrl}/mcp`, {
139
- method: "POST",
140
- headers: MCP_POST_HEADERS,
141
- body: initializeBody(),
142
- });
143
-
144
- expect(response.status).toBe(401);
145
- const body = await response.json();
146
- expect(body.error).toContain("Authorization");
147
- });
148
- });
149
-
150
- it("rejects non-initialize POST without session ID", async () => {
151
- const response = await fetch(`${baseUrl}/mcp`, {
152
- method: "POST",
153
- headers: {
154
- ...MCP_POST_HEADERS,
155
- Authorization: `Bearer ${BEARER_TOKEN}`,
156
- },
157
- body: JSON.stringify({
158
- jsonrpc: "2.0",
159
- method: "tools/list",
160
- id: 1,
161
- }),
162
- });
163
-
164
- expect(response.status).toBe(400);
165
- });
166
-
167
- it("accepts initialize request with Bearer token and returns session ID", async () => {
168
- const response = await fetch(`${baseUrl}/mcp`, {
169
- method: "POST",
170
- headers: mcpHeaders(),
171
- body: initializeBody(),
172
- });
173
-
174
- expect(response.status).toBe(200);
175
- const sessionId = response.headers.get("mcp-session-id");
176
- expect(sessionId).toBeTruthy();
177
- });
178
-
179
- it("lists all tools after initialization", async () => {
180
- const initResponse = await fetch(`${baseUrl}/mcp`, {
181
- method: "POST",
182
- headers: mcpHeaders(),
183
- body: initializeBody(),
184
- });
185
-
186
- const sessionId = initResponse.headers.get("mcp-session-id")!;
187
-
188
- // Send initialized notification
189
- await fetch(`${baseUrl}/mcp`, {
190
- method: "POST",
191
- headers: mcpHeaders({ sessionId }),
192
- body: JSON.stringify({
193
- jsonrpc: "2.0",
194
- method: "notifications/initialized",
195
- }),
196
- });
197
-
198
- // List tools
199
- const toolsResponse = await fetch(`${baseUrl}/mcp`, {
200
- method: "POST",
201
- headers: mcpHeaders({ sessionId }),
202
- body: JSON.stringify({
203
- jsonrpc: "2.0",
204
- method: "tools/list",
205
- id: 2,
206
- }),
207
- });
208
-
209
- expect(toolsResponse.status).toBe(200);
210
- const text = await toolsResponse.text();
211
- expect(text).toContain("fetch_langwatch_docs");
212
- expect(text).toContain("discover_schema");
213
- expect(text).toContain("search_traces");
214
- expect(text).toContain("platform_create_prompt");
215
- });
216
- });
217
-
218
- describe("DELETE /mcp", () => {
219
- it("closes an existing session", async () => {
220
- const initResponse = await fetch(`${baseUrl}/mcp`, {
221
- method: "POST",
222
- headers: mcpHeaders(),
223
- body: initializeBody(),
224
- });
225
-
226
- const sessionId = initResponse.headers.get("mcp-session-id")!;
227
-
228
- const deleteResponse = await fetch(`${baseUrl}/mcp`, {
229
- method: "DELETE",
230
- headers: {
231
- "mcp-session-id": sessionId,
232
- Authorization: `Bearer ${BEARER_TOKEN}`,
233
- },
234
- });
235
-
236
- expect(deleteResponse.status).toBe(200);
237
- });
238
-
239
- it("returns 404 for unknown session", async () => {
240
- const response = await fetch(`${baseUrl}/mcp`, {
241
- method: "DELETE",
242
- headers: {
243
- "mcp-session-id": "nonexistent-session-id",
244
- Authorization: `Bearer ${BEARER_TOKEN}`,
245
- },
246
- });
247
-
248
- expect(response.status).toBe(404);
249
- });
250
- });
251
-
252
- describe("OAuth 2.0 endpoints", () => {
253
- describe("/.well-known/oauth-authorization-server", () => {
254
- it("returns OAuth metadata with token endpoint", async () => {
255
- const response = await fetch(
256
- `${baseUrl}/.well-known/oauth-authorization-server`
257
- );
258
- const body = await response.json();
259
-
260
- expect(response.status).toBe(200);
261
- expect(body.token_endpoint).toContain("/oauth/token");
262
- expect(body.grant_types_supported).toContain("client_credentials");
263
- });
264
- });
265
-
266
- describe("/oauth/token", () => {
267
- it("returns 400 for unsupported grant type", async () => {
268
- const response = await fetch(`${baseUrl}/oauth/token`, {
269
- method: "POST",
270
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
271
- body: "grant_type=authorization_code&client_secret=test-key",
272
- });
273
- const body = await response.json();
274
-
275
- expect(response.status).toBe(400);
276
- expect(body.error).toBe("unsupported_grant_type");
277
- });
278
-
279
- it("returns 400 when client_secret is missing", async () => {
280
- const response = await fetch(`${baseUrl}/oauth/token`, {
281
- method: "POST",
282
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
283
- body: "grant_type=client_credentials",
284
- });
285
- const body = await response.json();
286
-
287
- expect(response.status).toBe(400);
288
- expect(body.error).toBe("invalid_request");
289
- });
290
-
291
- it("issues an access token for valid client credentials", async () => {
292
- const response = await fetch(`${baseUrl}/oauth/token`, {
293
- method: "POST",
294
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
295
- body: "grant_type=client_credentials&client_secret=my-langwatch-api-key",
296
- });
297
- const body = await response.json();
298
-
299
- expect(response.status).toBe(200);
300
- expect(body.access_token).toBeTruthy();
301
- expect(body.token_type).toBe("Bearer");
302
- expect(body.expires_in).toBe(3600);
303
- });
304
-
305
- it("issued token works for MCP initialize request", async () => {
306
- // Get OAuth token
307
- const tokenResponse = await fetch(`${baseUrl}/oauth/token`, {
308
- method: "POST",
309
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
310
- body: `grant_type=client_credentials&client_secret=${BEARER_TOKEN}`,
311
- });
312
- expect(tokenResponse.status).toBe(200);
313
- const { access_token } = await tokenResponse.json();
314
- expect(access_token).toBeTruthy();
315
-
316
- // Use OAuth token for MCP initialize
317
- const response = await fetch(`${baseUrl}/mcp`, {
318
- method: "POST",
319
- headers: {
320
- ...MCP_POST_HEADERS,
321
- Authorization: `Bearer ${access_token}`,
322
- },
323
- body: initializeBody(),
324
- });
325
-
326
- expect(response.status).toBe(200);
327
- expect(response.headers.get("mcp-session-id")).toBeTruthy();
328
- });
329
-
330
- it("issued token works for SSE connection", async () => {
331
- const controller = new AbortController();
332
-
333
- // Get OAuth token
334
- const tokenResponse = await fetch(`${baseUrl}/oauth/token`, {
335
- method: "POST",
336
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
337
- body: `grant_type=client_credentials&client_secret=${BEARER_TOKEN}`,
338
- });
339
- expect(tokenResponse.status).toBe(200);
340
- const { access_token } = await tokenResponse.json();
341
- expect(access_token).toBeTruthy();
342
-
343
- // Use OAuth token for SSE
344
- const response = await fetch(`${baseUrl}/sse`, {
345
- signal: controller.signal,
346
- headers: { Authorization: `Bearer ${access_token}` },
347
- });
348
-
349
- expect(response.status).toBe(200);
350
- expect(response.headers.get("content-type")).toContain(
351
- "text/event-stream"
352
- );
353
-
354
- controller.abort();
355
- });
356
- });
357
- });
358
-
359
- describe("/sse endpoint (legacy SSE)", () => {
360
- it("returns 401 without authorization", async () => {
361
- const controller = new AbortController();
362
-
363
- const response = await fetch(`${baseUrl}/sse`, {
364
- signal: controller.signal,
365
- });
366
-
367
- expect(response.status).toBe(401);
368
- controller.abort();
369
- });
370
-
371
- it("establishes SSE connection with Bearer token in header", async () => {
372
- const controller = new AbortController();
373
-
374
- const response = await fetch(`${baseUrl}/sse`, {
375
- signal: controller.signal,
376
- headers: { Authorization: `Bearer ${BEARER_TOKEN}` },
377
- });
378
-
379
- expect(response.status).toBe(200);
380
- expect(response.headers.get("content-type")).toContain(
381
- "text/event-stream"
382
- );
383
-
384
- const reader = response.body!.getReader();
385
- const decoder = new TextDecoder();
386
- const { value } = await reader.read();
387
- const text = decoder.decode(value);
388
-
389
- expect(text).toContain("event: endpoint");
390
- expect(text).toContain("/messages?sessionId=");
391
-
392
- controller.abort();
393
- });
394
- });
395
- });
@@ -1,284 +0,0 @@
1
- import { createServer, type Server } from "http";
2
- import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
- import { initConfig } from "../config.js";
4
-
5
- // --- Canned responses for each API endpoint ---
6
-
7
- const CANNED_TRACES_SEARCH = {
8
- traces: [
9
- {
10
- trace_id: "trace-001",
11
- formatted_trace: "Root [server] 1200ms\n LLM Call [llm] 500ms\n Input: Hello, how are you?\n Output: I am fine, thank you!",
12
- input: { value: "Hello, how are you?" },
13
- output: { value: "I am fine, thank you!" },
14
- timestamps: { started_at: 1700000000000 },
15
- metadata: { user_id: "user-42" },
16
- },
17
- ],
18
- pagination: { totalHits: 1 },
19
- };
20
-
21
- const CANNED_TRACE_DETAIL = {
22
- trace_id: "trace-001",
23
- formatted_trace: "Root [server] 1200ms\n LLM Call [llm] 500ms\n Input: Hello\n Output: Hi there",
24
- timestamps: {
25
- started_at: 1700000000000,
26
- inserted_at: 1700000001000,
27
- },
28
- metadata: { user_id: "user-42", thread_id: "thread-1" },
29
- evaluations: [
30
- {
31
- evaluator_id: "eval-1",
32
- name: "Faithfulness",
33
- score: 0.95,
34
- passed: true,
35
- },
36
- ],
37
- };
38
-
39
- const CANNED_ANALYTICS = {
40
- currentPeriod: [
41
- { date: "2024-01-01", "0__trace_id_cardinality": 42 },
42
- { date: "2024-01-02", "0__trace_id_cardinality": 58 },
43
- ],
44
- previousPeriod: [],
45
- };
46
-
47
- const CANNED_PROMPTS_LIST = [
48
- {
49
- id: "p1",
50
- handle: "greeting-bot",
51
- name: "Greeting Bot",
52
- latestVersionNumber: 3,
53
- },
54
- {
55
- id: "p2",
56
- handle: "qa-assistant",
57
- name: "QA Assistant",
58
- latestVersionNumber: 1,
59
- },
60
- ];
61
-
62
- const CANNED_PROMPT_DETAIL = {
63
- id: "p1",
64
- handle: "greeting-bot",
65
- name: "Greeting Bot",
66
- version: 3,
67
- versionId: "ver_p1v3",
68
- commitMessage: "Updated tone",
69
- model: "openai/gpt-4o",
70
- messages: [{ role: "system", content: "You are a friendly bot." }],
71
- parameters: {},
72
- tags: [{ name: "latest", versionId: "ver_p1v3" }],
73
- };
74
-
75
- const CANNED_PROMPT_CREATED = {
76
- id: "p-new",
77
- handle: "new-prompt",
78
- name: "New Prompt",
79
- latestVersionNumber: 1,
80
- };
81
-
82
- const CANNED_PROMPT_UPDATED = {
83
- id: "p1",
84
- handle: "greeting-bot",
85
- latestVersionNumber: 4,
86
- };
87
-
88
- // --- Mock HTTP Server ---
89
-
90
- function createMockServer(): Server {
91
- return createServer((req, res) => {
92
- const authToken = req.headers["x-auth-token"];
93
- if (authToken !== "test-integration-key") {
94
- res.writeHead(401, { "Content-Type": "application/json" });
95
- res.end(JSON.stringify({ message: "Invalid auth token." }));
96
- return;
97
- }
98
-
99
- let body = "";
100
- req.on("data", (chunk: string) => (body += chunk));
101
- req.on("end", () => {
102
- const url = req.url ?? "";
103
- res.setHeader("Content-Type", "application/json");
104
-
105
- if (url === "/api/traces/search" && req.method === "POST") {
106
- res.writeHead(200);
107
- res.end(JSON.stringify(CANNED_TRACES_SEARCH));
108
- } else if (
109
- url.match(/^\/api\/traces\/[^/]+(\?|$)/) &&
110
- req.method === "GET"
111
- ) {
112
- res.writeHead(200);
113
- res.end(JSON.stringify(CANNED_TRACE_DETAIL));
114
- } else if (
115
- url === "/api/analytics/timeseries" &&
116
- req.method === "POST"
117
- ) {
118
- res.writeHead(200);
119
- res.end(JSON.stringify(CANNED_ANALYTICS));
120
- } else if (url === "/api/prompts" && req.method === "GET") {
121
- res.writeHead(200);
122
- res.end(JSON.stringify(CANNED_PROMPTS_LIST));
123
- } else if (url.match(/^\/api\/prompts\/[^/]+$/) && req.method === "GET") {
124
- res.writeHead(200);
125
- res.end(JSON.stringify(CANNED_PROMPT_DETAIL));
126
- } else if (url === "/api/prompts" && req.method === "POST") {
127
- res.writeHead(200);
128
- res.end(JSON.stringify(CANNED_PROMPT_CREATED));
129
- } else if (
130
- url.match(/^\/api\/prompts\/[^/]+$/) &&
131
- req.method === "PUT"
132
- ) {
133
- res.writeHead(200);
134
- res.end(JSON.stringify(CANNED_PROMPT_UPDATED));
135
- } else {
136
- res.writeHead(404);
137
- res.end(
138
- JSON.stringify({ message: `Not found: ${req.method} ${url}` })
139
- );
140
- }
141
- });
142
- });
143
- }
144
-
145
- // --- Integration Tests ---
146
-
147
- describe("MCP tools integration", () => {
148
- let server: Server;
149
- let port: number;
150
-
151
- beforeAll(async () => {
152
- server = createMockServer();
153
- await new Promise<void>((resolve) => {
154
- server.listen(0, () => {
155
- const addr = server.address();
156
- port = typeof addr === "object" && addr ? addr.port : 0;
157
- initConfig({
158
- apiKey: "test-integration-key",
159
- endpoint: `http://localhost:${port}`,
160
- });
161
- resolve();
162
- });
163
- });
164
- });
165
-
166
- afterAll(async () => {
167
- await new Promise<void>((resolve) => server.close(() => resolve()));
168
- });
169
-
170
- describe("search_traces", () => {
171
- it("returns formatted trace digests from mock server", async () => {
172
- const { handleSearchTraces } = await import(
173
- "../tools/search-traces.js"
174
- );
175
- const result = await handleSearchTraces({
176
- startDate: "24h",
177
- endDate: "now",
178
- });
179
- expect(result).toContain("trace-001");
180
- expect(result).toContain("LLM Call [llm] 500ms");
181
- expect(result).toContain("1 trace");
182
- });
183
- });
184
-
185
- describe("get_trace", () => {
186
- it("returns formatted trace digest from mock server", async () => {
187
- const { handleGetTrace } = await import("../tools/get-trace.js");
188
- const result = await handleGetTrace({ traceId: "trace-001" });
189
- expect(result).toContain("trace-001");
190
- expect(result).toContain("LLM Call [llm] 500ms");
191
- expect(result).toContain("Faithfulness");
192
- expect(result).toContain("PASSED");
193
- });
194
- });
195
-
196
- describe("get_analytics", () => {
197
- it("returns formatted analytics data from mock server", async () => {
198
- const { handleGetAnalytics } = await import(
199
- "../tools/get-analytics.js"
200
- );
201
- const result = await handleGetAnalytics({
202
- metric: "metadata.trace_id",
203
- aggregation: "cardinality",
204
- startDate: "7d",
205
- });
206
- expect(result).toContain("42");
207
- expect(result).toContain("58");
208
- });
209
- });
210
-
211
- describe("platform_list_prompts", () => {
212
- it("returns formatted prompt list from mock server", async () => {
213
- const { handleListPrompts } = await import("../tools/list-prompts.js");
214
- const result = await handleListPrompts();
215
- expect(result).toContain("greeting-bot");
216
- expect(result).toContain("Greeting Bot");
217
- expect(result).toContain("qa-assistant");
218
- });
219
- });
220
-
221
- describe("platform_get_prompt", () => {
222
- it("returns formatted prompt details from mock server", async () => {
223
- const { handleGetPrompt } = await import("../tools/get-prompt.js");
224
- const result = await handleGetPrompt({ idOrHandle: "greeting-bot" });
225
- expect(result).toContain("Greeting Bot");
226
- expect(result).toContain("gpt-4o");
227
- expect(result).toContain("You are a friendly bot.");
228
- expect(result).toContain("v3");
229
- });
230
- });
231
-
232
- describe("platform_create_prompt", () => {
233
- it("returns success message from mock server", async () => {
234
- const { handleCreatePrompt } = await import(
235
- "../tools/create-prompt.js"
236
- );
237
- const result = await handleCreatePrompt({
238
- name: "New Prompt",
239
- messages: [{ role: "system", content: "You are helpful." }],
240
- model: "openai/gpt-4o",
241
- });
242
- expect(result).toContain("created successfully");
243
- expect(result).toContain("p-new");
244
- });
245
- });
246
-
247
- describe("platform_update_prompt", () => {
248
- it("returns success message from mock server", async () => {
249
- const { handleUpdatePrompt } = await import(
250
- "../tools/update-prompt.js"
251
- );
252
- const result = await handleUpdatePrompt({
253
- idOrHandle: "greeting-bot",
254
- model: "openai/gpt-4o-mini",
255
- commitMessage: "Switch to mini",
256
- });
257
- expect(result).toContain("updated successfully");
258
- expect(result).toContain("Switch to mini");
259
- });
260
- });
261
-
262
- describe("when API key is invalid", () => {
263
- afterAll(() => {
264
- initConfig({
265
- apiKey: "test-integration-key",
266
- endpoint: `http://localhost:${port}`,
267
- });
268
- });
269
-
270
- it("throws an error with 401 status", async () => {
271
- initConfig({
272
- apiKey: "bad-key",
273
- endpoint: `http://localhost:${port}`,
274
- });
275
-
276
- const { handleSearchTraces } = await import(
277
- "../tools/search-traces.js"
278
- );
279
- await expect(
280
- handleSearchTraces({ startDate: "24h" })
281
- ).rejects.toThrow("401");
282
- });
283
- });
284
- });