@langwatch/mcp-server 0.6.1 → 0.8.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 (241) hide show
  1. package/.release-please-shim +1 -0
  2. package/CHANGELOG.md +89 -0
  3. package/README.md +51 -8
  4. package/dist/{archive-scenario-YFD5THOR.js → archive-scenario-YKGLJ4MZ.js} +4 -4
  5. package/dist/archive-suite-QFNDO3Y3.js +15 -0
  6. package/dist/assign-prompt-tag-Y2B4CBBT.js +19 -0
  7. package/dist/chunk-B57MZ4WI.js +1573 -0
  8. package/dist/{chunk-IX6QJKAD.js → chunk-CPUPGDNA.js} +2 -2
  9. package/dist/chunk-FBRKHHJV.js +48 -0
  10. package/dist/{chunk-5UOPNRXW.js → chunk-HDJDFKZR.js} +10 -3
  11. package/dist/chunk-KOO5733S.js +72 -0
  12. package/dist/chunk-KZNBCKWG.js +39 -0
  13. package/dist/chunk-L6QENXYA.js +42 -0
  14. package/dist/{chunk-6U4TCGFC.js → chunk-NACSR6B7.js} +2 -2
  15. package/dist/chunk-NUFPTHKU.js +9 -0
  16. package/dist/chunk-OVQF3D5R.js +86 -0
  17. package/dist/chunk-PO7FM7IX.js +35 -0
  18. package/dist/chunk-PZUWCWOS.js +25 -0
  19. package/dist/chunk-WVI5CJ6S.js +21 -0
  20. package/dist/{chunk-LLRQIF52.js → chunk-YH2IBTEL.js} +54 -6
  21. package/dist/chunk-YI3OG4PI.js +71 -0
  22. package/dist/config.d.ts +17 -0
  23. package/dist/config.js +13 -0
  24. package/dist/create-agent-YRSDH7P7.js +23 -0
  25. package/dist/create-annotation-FYQNKMVJ.js +24 -0
  26. package/dist/create-dashboard-CORBR4YQ.js +18 -0
  27. package/dist/create-dataset-ZC63T6BB.js +22 -0
  28. package/dist/create-dataset-records-ILVNVKVR.js +22 -0
  29. package/dist/{create-evaluator-E5X5ZP3B.js → create-evaluator-2AU3PXFB.js} +4 -4
  30. package/dist/create-mcp-server.d.ts +8 -0
  31. package/dist/create-mcp-server.js +8 -0
  32. package/dist/{create-prompt-7Z35MIL6.js → create-prompt-NKRJ47YY.js} +7 -4
  33. package/dist/create-prompt-tag-S4JX3ULL.js +17 -0
  34. package/dist/{create-scenario-DIMPJRPY.js → create-scenario-BPRF75KF.js} +4 -4
  35. package/dist/create-suite-4YN7D6K2.js +38 -0
  36. package/dist/delete-agent-Y72R2YQA.js +18 -0
  37. package/dist/delete-annotation-UHWDMHSH.js +17 -0
  38. package/dist/delete-dashboard-LPWT36KN.js +18 -0
  39. package/dist/delete-dataset-GGPQRHKX.js +20 -0
  40. package/dist/delete-dataset-records-LTG5LT26.js +21 -0
  41. package/dist/delete-evaluator-F7QLXDHU.js +15 -0
  42. package/dist/delete-prompt-tag-B5UKZL45.js +17 -0
  43. package/dist/delete-workflow-4DGUDIDE.js +17 -0
  44. package/dist/get-agent-YEVICUX4.js +28 -0
  45. package/dist/{get-analytics-4YJW4S5L.js → get-analytics-3W5CMU3F.js} +22 -5
  46. package/dist/get-dashboard-NCQHN6MW.js +29 -0
  47. package/dist/get-dataset-KBK6PH36.js +48 -0
  48. package/dist/{get-evaluator-WDEH2F7M.js → get-evaluator-QDUL5LXR.js} +4 -4
  49. package/dist/{get-prompt-F6PDVC76.js → get-prompt-XCSSNRKR.js} +4 -4
  50. package/dist/{get-scenario-H24ZYNT5.js → get-scenario-FNRKOY7E.js} +4 -4
  51. package/dist/get-simulation-run-WOEKUF7K.js +56 -0
  52. package/dist/get-suite-U5AOD5TC.js +44 -0
  53. package/dist/{get-trace-27USKGO7.js → get-trace-MUWEJM2Z.js} +3 -3
  54. package/dist/get-workflow-SOA7MT7L.js +25 -0
  55. package/dist/http-server-7DMOCB75.js +224 -0
  56. package/dist/index.js +61640 -31868
  57. package/dist/langwatch-api-annotations-Q57NDUVR.js +17 -0
  58. package/dist/langwatch-api-dashboards-VBWWXV3Y.js +17 -0
  59. package/dist/langwatch-api-monitors-L3IY7FDT.js +52 -0
  60. package/dist/langwatch-api-secrets-S5HHF3XR.js +40 -0
  61. package/dist/langwatch-api-triggers-ME33QE26.js +30 -0
  62. package/dist/langwatch-api-workflows-4CJQAYP2.js +15 -0
  63. package/dist/list-agents-3HGIBJFM.js +32 -0
  64. package/dist/list-annotations-KWXYVEPI.js +33 -0
  65. package/dist/list-dashboards-VQ2LH666.js +32 -0
  66. package/dist/list-dataset-records-RNRGROJP.js +39 -0
  67. package/dist/list-datasets-I4A2LT2S.js +60 -0
  68. package/dist/{list-evaluators-KRGI72EH.js → list-evaluators-AKKRJ5MX.js} +4 -4
  69. package/dist/{list-model-providers-A5YCFTPI.js → list-model-providers-DVFEHFHZ.js} +4 -4
  70. package/dist/list-prompt-tags-PL5OISUA.js +23 -0
  71. package/dist/{list-prompts-LKJSE7XN.js → list-prompts-7VTFWE2Z.js} +3 -3
  72. package/dist/{list-scenarios-ZK5CMGC4.js → list-scenarios-5BZWZ6ZN.js} +4 -4
  73. package/dist/list-simulation-runs-WCZ6RLPE.js +43 -0
  74. package/dist/list-suites-RRQ2JX5Y.js +42 -0
  75. package/dist/list-workflows-UQB5FCX5.js +35 -0
  76. package/dist/rename-prompt-tag-TURD6KYU.js +18 -0
  77. package/dist/run-agent-BEJ4K4CM.js +36 -0
  78. package/dist/run-evaluation-AJ7WZNQD.js +64 -0
  79. package/dist/run-suite-U7V432G2.js +29 -0
  80. package/dist/run-workflow-5WX7DK5T.js +36 -0
  81. package/dist/{search-traces-SOKAAMAR.js → search-traces-ZCHNOMTX.js} +3 -3
  82. package/dist/{set-model-provider-7MGULZDH.js → set-model-provider-6CFHMCNE.js} +4 -4
  83. package/dist/update-agent-UE6UWLZP.js +20 -0
  84. package/dist/update-dataset-4XQZZE4S.js +22 -0
  85. package/dist/update-dataset-record-GNNM5TKM.js +19 -0
  86. package/dist/{update-evaluator-A3XINFLJ.js → update-evaluator-LHVDXIZD.js} +4 -4
  87. package/dist/{update-prompt-IW7X2UQM.js → update-prompt-3XEHECJ7.js} +5 -3
  88. package/dist/{update-scenario-ZT7TOBFR.js → update-scenario-DFPREYCD.js} +4 -4
  89. package/dist/update-suite-RATU5THO.js +39 -0
  90. package/package.json +22 -8
  91. package/src/__tests__/all-tools.integration.test.ts +353 -0
  92. package/src/__tests__/config.unit.test.ts +81 -1
  93. package/src/__tests__/datasets.integration.test.ts +620 -0
  94. package/src/__tests__/datasets.unit.test.ts +244 -0
  95. package/src/__tests__/docker.integration.test.ts +234 -0
  96. package/src/__tests__/http-transport.integration.test.ts +397 -0
  97. package/src/__tests__/langwatch-api.unit.test.ts +174 -0
  98. package/src/__tests__/scenario-tools.unit.test.ts +3 -0
  99. package/src/__tests__/tools.unit.test.ts +177 -0
  100. package/src/config.d.ts +15 -0
  101. package/src/config.ts +85 -7
  102. package/src/create-mcp-server.d.ts +6 -0
  103. package/src/create-mcp-server.ts +1799 -0
  104. package/src/http-server.ts +329 -0
  105. package/src/index.ts +22 -593
  106. package/src/langwatch-api-agents.ts +108 -0
  107. package/src/langwatch-api-annotations.ts +49 -0
  108. package/src/langwatch-api-dashboards.ts +48 -0
  109. package/src/langwatch-api-datasets.ts +191 -0
  110. package/src/langwatch-api-evaluators.ts +10 -0
  111. package/src/langwatch-api-monitors.ts +82 -0
  112. package/src/langwatch-api-secrets.ts +48 -0
  113. package/src/langwatch-api-simulation-runs.ts +51 -0
  114. package/src/langwatch-api-suites.ts +118 -0
  115. package/src/langwatch-api-triggers.ts +48 -0
  116. package/src/langwatch-api-workflows.ts +41 -0
  117. package/src/langwatch-api.ts +65 -3
  118. package/src/schemas/create-dataset.ts +48 -0
  119. package/src/schemas/index.ts +1 -0
  120. package/src/tools/archive-suite.ts +12 -0
  121. package/src/tools/assign-prompt-tag.ts +16 -0
  122. package/src/tools/create-agent.ts +15 -0
  123. package/src/tools/create-annotation.ts +18 -0
  124. package/src/tools/create-dashboard.ts +7 -0
  125. package/src/tools/create-dataset-records.ts +23 -0
  126. package/src/tools/create-dataset.ts +22 -0
  127. package/src/tools/create-prompt-tag.ts +12 -0
  128. package/src/tools/create-prompt.ts +4 -0
  129. package/src/tools/create-suite.ts +42 -0
  130. package/src/tools/delete-agent.ts +7 -0
  131. package/src/tools/delete-annotation.ts +7 -0
  132. package/src/tools/delete-dashboard.ts +7 -0
  133. package/src/tools/delete-dataset-records.ts +22 -0
  134. package/src/tools/delete-dataset.ts +20 -0
  135. package/src/tools/delete-evaluator.ts +12 -0
  136. package/src/tools/delete-prompt-tag.ts +12 -0
  137. package/src/tools/delete-workflow.ts +7 -0
  138. package/src/tools/format-dataset-mutation.ts +25 -0
  139. package/src/tools/get-agent.ts +21 -0
  140. package/src/tools/get-analytics.ts +30 -3
  141. package/src/tools/get-dashboard.ts +22 -0
  142. package/src/tools/get-dataset.ts +63 -0
  143. package/src/tools/get-prompt.ts +2 -1
  144. package/src/tools/get-simulation-run.ts +60 -0
  145. package/src/tools/get-suite.ts +47 -0
  146. package/src/tools/get-workflow.ts +17 -0
  147. package/src/tools/list-agents.ts +27 -0
  148. package/src/tools/list-annotations.ts +33 -0
  149. package/src/tools/list-dashboards.ts +27 -0
  150. package/src/tools/list-dataset-records.ts +46 -0
  151. package/src/tools/list-datasets.ts +80 -0
  152. package/src/tools/list-prompt-tags.ts +21 -0
  153. package/src/tools/list-simulation-runs.ts +49 -0
  154. package/src/tools/list-suites.ts +43 -0
  155. package/src/tools/list-workflows.ts +31 -0
  156. package/src/tools/rename-prompt-tag.ts +14 -0
  157. package/src/tools/run-agent.ts +36 -0
  158. package/src/tools/run-evaluation.ts +87 -0
  159. package/src/tools/run-suite.ts +28 -0
  160. package/src/tools/run-workflow.ts +36 -0
  161. package/src/tools/update-agent.ts +13 -0
  162. package/src/tools/update-dataset-record.ts +21 -0
  163. package/src/tools/update-dataset.ts +23 -0
  164. package/src/tools/update-prompt.ts +3 -0
  165. package/src/tools/update-suite.ts +44 -0
  166. package/src/utils/escape-markdown.ts +12 -0
  167. package/uv.lock +188 -530
  168. package/build.js +0 -12
  169. package/dist/archive-scenario-YFD5THOR.js.map +0 -1
  170. package/dist/chunk-5UOPNRXW.js.map +0 -1
  171. package/dist/chunk-6U4TCGFC.js.map +0 -1
  172. package/dist/chunk-AAQNA53E.js +0 -28
  173. package/dist/chunk-AAQNA53E.js.map +0 -1
  174. package/dist/chunk-IX6QJKAD.js.map +0 -1
  175. package/dist/chunk-LLRQIF52.js.map +0 -1
  176. package/dist/chunk-ZXKLPC2E.js.map +0 -1
  177. package/dist/config-FIQWQRUB.js +0 -11
  178. package/dist/config-FIQWQRUB.js.map +0 -1
  179. package/dist/create-evaluator-E5X5ZP3B.js.map +0 -1
  180. package/dist/create-prompt-7Z35MIL6.js.map +0 -1
  181. package/dist/create-scenario-DIMPJRPY.js.map +0 -1
  182. package/dist/discover-evaluator-schema-H23XCLNE.js.map +0 -1
  183. package/dist/discover-scenario-schema-MEEEVND7.js.map +0 -1
  184. package/dist/discover-schema-3T52ORPB.js.map +0 -1
  185. package/dist/get-analytics-4YJW4S5L.js.map +0 -1
  186. package/dist/get-evaluator-WDEH2F7M.js.map +0 -1
  187. package/dist/get-prompt-F6PDVC76.js.map +0 -1
  188. package/dist/get-scenario-H24ZYNT5.js.map +0 -1
  189. package/dist/get-trace-27USKGO7.js.map +0 -1
  190. package/dist/index.js.map +0 -1
  191. package/dist/list-evaluators-KRGI72EH.js.map +0 -1
  192. package/dist/list-model-providers-A5YCFTPI.js.map +0 -1
  193. package/dist/list-prompts-LKJSE7XN.js.map +0 -1
  194. package/dist/list-scenarios-ZK5CMGC4.js.map +0 -1
  195. package/dist/search-traces-SOKAAMAR.js.map +0 -1
  196. package/dist/set-model-provider-7MGULZDH.js.map +0 -1
  197. package/dist/update-evaluator-A3XINFLJ.js.map +0 -1
  198. package/dist/update-prompt-IW7X2UQM.js.map +0 -1
  199. package/dist/update-scenario-ZT7TOBFR.js.map +0 -1
  200. package/tests/evaluations.ipynb +0 -649
  201. package/tests/fixtures/azure/azure_openai_stream_bot_expected.py +0 -102
  202. package/tests/fixtures/azure/azure_openai_stream_bot_input.py +0 -78
  203. package/tests/fixtures/dspy/dspy_bot_expected.py +0 -61
  204. package/tests/fixtures/dspy/dspy_bot_input.py +0 -53
  205. package/tests/fixtures/fastapi/fastapi_app_expected.py +0 -68
  206. package/tests/fixtures/fastapi/fastapi_app_input.py +0 -60
  207. package/tests/fixtures/fastapi/prompt_management_fastapi_expected.py +0 -114
  208. package/tests/fixtures/fastapi/prompt_management_fastapi_input.py +0 -88
  209. package/tests/fixtures/haystack/haystack_bot_expected.py +0 -141
  210. package/tests/fixtures/haystack/haystack_bot_input.py +0 -69
  211. package/tests/fixtures/langchain/langchain_bot_expected.py +0 -53
  212. package/tests/fixtures/langchain/langchain_bot_input.py +0 -45
  213. package/tests/fixtures/langchain/langchain_bot_with_memory_expected.py +0 -69
  214. package/tests/fixtures/langchain/langchain_bot_with_memory_input.py +0 -61
  215. package/tests/fixtures/langchain/langchain_rag_bot_expected.py +0 -97
  216. package/tests/fixtures/langchain/langchain_rag_bot_input.py +0 -77
  217. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_expected.py +0 -116
  218. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_input.py +0 -81
  219. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_expected.py +0 -331
  220. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_input.py +0 -106
  221. package/tests/fixtures/litellm/litellm_bot_expected.py +0 -40
  222. package/tests/fixtures/litellm/litellm_bot_input.py +0 -35
  223. package/tests/fixtures/openai/openai_bot_expected.py +0 -43
  224. package/tests/fixtures/openai/openai_bot_function_call_expected.py +0 -91
  225. package/tests/fixtures/openai/openai_bot_function_call_input.py +0 -82
  226. package/tests/fixtures/openai/openai_bot_input.py +0 -36
  227. package/tests/fixtures/openai/openai_bot_rag_expected.py +0 -73
  228. package/tests/fixtures/openai/openai_bot_rag_input.py +0 -51
  229. package/tests/fixtures/opentelemetry/openinference_dspy_bot_expected.py +0 -63
  230. package/tests/fixtures/opentelemetry/openinference_dspy_bot_input.py +0 -58
  231. package/tests/fixtures/opentelemetry/openinference_langchain_bot_expected.py +0 -53
  232. package/tests/fixtures/opentelemetry/openinference_langchain_bot_input.py +0 -52
  233. package/tests/fixtures/opentelemetry/openinference_openai_bot_expected.py +0 -49
  234. package/tests/fixtures/opentelemetry/openinference_openai_bot_input.py +0 -41
  235. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_expected.py +0 -44
  236. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_input.py +0 -40
  237. package/tests/fixtures/strands/strands_bot_expected.py +0 -84
  238. package/tests/fixtures/strands/strands_bot_input.py +0 -52
  239. package/tests/scenario-openai.test.ts +0 -160
  240. package/tsup.config.ts +0 -10
  241. package/vitest.config.js +0 -7
@@ -0,0 +1,118 @@
1
+ import { makeRequest } from "./langwatch-api.js";
2
+
3
+ // --- Suite types ---
4
+
5
+ export interface SuiteTarget {
6
+ type: "prompt" | "http" | "code" | "workflow";
7
+ referenceId: string;
8
+ }
9
+
10
+ export interface SuiteSummary {
11
+ id: string;
12
+ name: string;
13
+ slug: string;
14
+ description: string | null;
15
+ scenarioIds: string[];
16
+ targets: SuiteTarget[];
17
+ repeatCount: number;
18
+ labels: string[];
19
+ createdAt: string;
20
+ updatedAt: string;
21
+ }
22
+
23
+ export interface SuiteRunResult {
24
+ scheduled: boolean;
25
+ batchRunId: string;
26
+ setId: string;
27
+ jobCount: number;
28
+ skippedArchived: {
29
+ scenarios: string[];
30
+ targets: string[];
31
+ };
32
+ items: Array<{
33
+ scenarioRunId: string;
34
+ scenarioId: string;
35
+ target: SuiteTarget;
36
+ name: string | null;
37
+ }>;
38
+ }
39
+
40
+ export interface SuiteArchiveResponse {
41
+ id: string;
42
+ archived: boolean;
43
+ }
44
+
45
+ // --- Suite API functions ---
46
+
47
+ /** Lists all suites (run plans) in the project. */
48
+ export async function listSuites(): Promise<SuiteSummary[]> {
49
+ return makeRequest("GET", "/api/suites") as Promise<SuiteSummary[]>;
50
+ }
51
+
52
+ /** Retrieves a single suite by ID. */
53
+ export async function getSuite(id: string): Promise<SuiteSummary> {
54
+ return makeRequest(
55
+ "GET",
56
+ `/api/suites/${encodeURIComponent(id)}`
57
+ ) as Promise<SuiteSummary>;
58
+ }
59
+
60
+ /** Creates a new suite. */
61
+ export async function createSuite(data: {
62
+ name: string;
63
+ description?: string;
64
+ scenarioIds: string[];
65
+ targets: SuiteTarget[];
66
+ repeatCount?: number;
67
+ labels?: string[];
68
+ }): Promise<SuiteSummary> {
69
+ return makeRequest("POST", "/api/suites", data) as Promise<SuiteSummary>;
70
+ }
71
+
72
+ /** Updates an existing suite. */
73
+ export async function updateSuite(params: {
74
+ id: string;
75
+ name?: string;
76
+ description?: string | null;
77
+ scenarioIds?: string[];
78
+ targets?: SuiteTarget[];
79
+ repeatCount?: number;
80
+ labels?: string[];
81
+ }): Promise<SuiteSummary> {
82
+ const { id, ...data } = params;
83
+ return makeRequest(
84
+ "PATCH",
85
+ `/api/suites/${encodeURIComponent(id)}`,
86
+ data
87
+ ) as Promise<SuiteSummary>;
88
+ }
89
+
90
+ /** Duplicates a suite. */
91
+ export async function duplicateSuite(id: string): Promise<SuiteSummary> {
92
+ return makeRequest(
93
+ "POST",
94
+ `/api/suites/${encodeURIComponent(id)}/duplicate`
95
+ ) as Promise<SuiteSummary>;
96
+ }
97
+
98
+ /** Triggers a suite run. */
99
+ export async function runSuite(
100
+ id: string,
101
+ idempotencyKey?: string
102
+ ): Promise<SuiteRunResult> {
103
+ return makeRequest(
104
+ "POST",
105
+ `/api/suites/${encodeURIComponent(id)}/run`,
106
+ { idempotencyKey: idempotencyKey ?? `mcp-${Date.now()}-${Math.random().toString(36).slice(2)}` }
107
+ ) as Promise<SuiteRunResult>;
108
+ }
109
+
110
+ /** Archives (soft-deletes) a suite. */
111
+ export async function archiveSuite(
112
+ id: string
113
+ ): Promise<SuiteArchiveResponse> {
114
+ return makeRequest(
115
+ "DELETE",
116
+ `/api/suites/${encodeURIComponent(id)}`
117
+ ) as Promise<SuiteArchiveResponse>;
118
+ }
@@ -0,0 +1,48 @@
1
+ import { makeRequest } from "./langwatch-api.js";
2
+
3
+ export interface TriggerSummary {
4
+ id: string;
5
+ name: string;
6
+ action: string;
7
+ actionParams: Record<string, unknown>;
8
+ filters: Record<string, unknown>;
9
+ active: boolean;
10
+ message: string | null;
11
+ alertType: string | null;
12
+ createdAt: string;
13
+ updatedAt: string;
14
+ }
15
+
16
+ export async function listTriggers(): Promise<TriggerSummary[]> {
17
+ return makeRequest("GET", "/api/triggers") as Promise<TriggerSummary[]>;
18
+ }
19
+
20
+ export async function getTrigger(id: string): Promise<TriggerSummary> {
21
+ return makeRequest("GET", `/api/triggers/${encodeURIComponent(id)}`) as Promise<TriggerSummary>;
22
+ }
23
+
24
+ export async function createTrigger(data: {
25
+ name: string;
26
+ action: string;
27
+ actionParams?: Record<string, unknown>;
28
+ filters?: Record<string, unknown>;
29
+ message?: string;
30
+ alertType?: string;
31
+ }): Promise<TriggerSummary> {
32
+ return makeRequest("POST", "/api/triggers", data) as Promise<TriggerSummary>;
33
+ }
34
+
35
+ export async function updateTrigger(params: {
36
+ id: string;
37
+ name?: string;
38
+ active?: boolean;
39
+ message?: string | null;
40
+ alertType?: string | null;
41
+ }): Promise<TriggerSummary> {
42
+ const { id, ...data } = params;
43
+ return makeRequest("PATCH", `/api/triggers/${encodeURIComponent(id)}`, data) as Promise<TriggerSummary>;
44
+ }
45
+
46
+ export async function deleteTrigger(id: string): Promise<{ id: string; deleted: boolean }> {
47
+ return makeRequest("DELETE", `/api/triggers/${encodeURIComponent(id)}`) as Promise<{ id: string; deleted: boolean }>;
48
+ }
@@ -0,0 +1,41 @@
1
+ import { makeRequest } from "./langwatch-api.js";
2
+
3
+ export interface WorkflowSummary {
4
+ id: string;
5
+ name: string;
6
+ icon: string | null;
7
+ description: string | null;
8
+ isEvaluator: boolean;
9
+ isComponent: boolean;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ }
13
+
14
+ export async function listWorkflows(): Promise<WorkflowSummary[]> {
15
+ return makeRequest("GET", "/api/workflows") as Promise<WorkflowSummary[]>;
16
+ }
17
+
18
+ export async function getWorkflow(id: string): Promise<WorkflowSummary> {
19
+ return makeRequest(
20
+ "GET",
21
+ `/api/workflows/${encodeURIComponent(id)}`,
22
+ ) as Promise<WorkflowSummary>;
23
+ }
24
+
25
+ export async function runWorkflow(
26
+ id: string,
27
+ input?: Record<string, unknown>
28
+ ): Promise<Record<string, unknown>> {
29
+ return makeRequest(
30
+ "POST",
31
+ `/api/workflows/${encodeURIComponent(id)}/run`,
32
+ input ?? {},
33
+ ) as Promise<Record<string, unknown>>;
34
+ }
35
+
36
+ export async function deleteWorkflow(id: string): Promise<{ id: string; archived: boolean }> {
37
+ return makeRequest(
38
+ "DELETE",
39
+ `/api/workflows/${encodeURIComponent(id)}`,
40
+ ) as Promise<{ id: string; archived: boolean }>;
41
+ }
@@ -118,10 +118,14 @@ export async function makeRequest(
118
118
  path: string,
119
119
  body?: unknown
120
120
  ): Promise<unknown> {
121
- const url = getConfig().endpoint + path;
121
+ const config = getConfig();
122
+ const url = config.endpoint + path;
122
123
  const headers: Record<string, string> = {
123
124
  "X-Auth-Token": requireApiKey(),
124
125
  };
126
+ if (config.projectId) {
127
+ headers["X-Project-Id"] = config.projectId;
128
+ }
125
129
 
126
130
  if (body !== undefined) {
127
131
  headers["Content-Type"] = "application/json";
@@ -140,6 +144,9 @@ export async function makeRequest(
140
144
  );
141
145
  }
142
146
 
147
+ if (response.status === 204 || response.headers?.get("content-length") === "0") {
148
+ return null;
149
+ }
143
150
  return response.json();
144
151
  }
145
152
 
@@ -202,9 +209,12 @@ export async function listPrompts(): Promise<PromptSummary[]> {
202
209
  /** Retrieves a single prompt by ID or handle. */
203
210
  export async function getPrompt(
204
211
  idOrHandle: string,
205
- version?: number
212
+ options?: { version?: number; tag?: string }
206
213
  ): Promise<PromptDetailResponse> {
207
- const query = version != null ? `?version=${version}` : "";
214
+ const params = new URLSearchParams();
215
+ if (options?.version != null) params.set("version", String(options.version));
216
+ if (options?.tag) params.set("tag", options.tag);
217
+ const query = params.toString() ? `?${params}` : "";
208
218
  return makeRequest(
209
219
  "GET",
210
220
  `/api/prompts/${encodeURIComponent(idOrHandle)}${query}`
@@ -216,6 +226,7 @@ export async function createPrompt(data: {
216
226
  handle: string;
217
227
  messages: Array<{ role: string; content: string }>;
218
228
  model: string;
229
+ tags?: string[];
219
230
  }): Promise<PromptMutationResponse> {
220
231
  return makeRequest(
221
232
  "POST",
@@ -231,6 +242,7 @@ export async function updatePrompt(
231
242
  messages?: Array<{ role: string; content: string }>;
232
243
  model?: string;
233
244
  commitMessage: string;
245
+ tags?: string[];
234
246
  }
235
247
  ): Promise<PromptMutationResponse> {
236
248
  return makeRequest(
@@ -239,3 +251,53 @@ export async function updatePrompt(
239
251
  data
240
252
  ) as Promise<PromptMutationResponse>;
241
253
  }
254
+
255
+ /** Assigns a tag to a specific prompt version. */
256
+ export async function assignPromptTag({
257
+ idOrHandle,
258
+ tag,
259
+ versionId,
260
+ }: {
261
+ idOrHandle: string;
262
+ tag: string;
263
+ versionId: string;
264
+ }): Promise<unknown> {
265
+ return makeRequest(
266
+ "PUT",
267
+ `/api/prompts/${encodeURIComponent(idOrHandle)}/tags/${encodeURIComponent(tag)}`,
268
+ { versionId }
269
+ );
270
+ }
271
+
272
+ /** Lists all prompt tag definitions for the organization. */
273
+ export async function listPromptTags(): Promise<unknown> {
274
+ return makeRequest("GET", "/api/prompts/tags");
275
+ }
276
+
277
+ /** Creates a custom prompt tag definition. */
278
+ export async function createPromptTag(name: string): Promise<unknown> {
279
+ return makeRequest("POST", "/api/prompts/tags", { name });
280
+ }
281
+
282
+ /** Renames an existing prompt tag. */
283
+ export async function renamePromptTag({
284
+ tag,
285
+ name,
286
+ }: {
287
+ tag: string;
288
+ name: string;
289
+ }): Promise<unknown> {
290
+ return makeRequest(
291
+ "PUT",
292
+ `/api/prompts/tags/${encodeURIComponent(tag)}`,
293
+ { name }
294
+ );
295
+ }
296
+
297
+ /** Deletes a prompt tag and all its assignments. */
298
+ export async function deletePromptTag(tag: string): Promise<unknown> {
299
+ return makeRequest(
300
+ "DELETE",
301
+ `/api/prompts/tags/${encodeURIComponent(tag)}`
302
+ );
303
+ }
@@ -0,0 +1,48 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * All supported dataset column types on the LangWatch platform.
5
+ */
6
+ export const DATASET_COLUMN_TYPES = [
7
+ "string",
8
+ "boolean",
9
+ "number",
10
+ "date",
11
+ "list",
12
+ "json",
13
+ "spans",
14
+ "rag_contexts",
15
+ "chat_messages",
16
+ "annotations",
17
+ "evaluations",
18
+ "image",
19
+ ] as const;
20
+
21
+ /**
22
+ * Zod schema for a single dataset column type value.
23
+ */
24
+ export const datasetColumnTypeSchema = z.enum(DATASET_COLUMN_TYPES);
25
+
26
+ /**
27
+ * Zod schema for a dataset column definition (name + type).
28
+ *
29
+ * Shared between create and update tool registrations.
30
+ */
31
+ export const datasetColumnDefinitionSchema = z.object({
32
+ name: z.string().describe("Column name"),
33
+ type: datasetColumnTypeSchema.describe("Column type"),
34
+ });
35
+
36
+ /**
37
+ * Zod schema for the platform_create_dataset MCP tool parameters.
38
+ *
39
+ * Extracted so it can be shared between the MCP tool registration
40
+ * (create-mcp-server.ts) and unit tests.
41
+ */
42
+ export const createDatasetSchema = z.object({
43
+ name: z.string().min(1).describe("Dataset name"),
44
+ columnTypes: z
45
+ .array(datasetColumnDefinitionSchema)
46
+ .optional()
47
+ .describe("Column definitions for the dataset"),
48
+ });
@@ -1,3 +1,4 @@
1
1
  export { filterFields, type FilterFieldInfo } from "./filter-fields.js";
2
2
  export { analyticsMetrics, type MetricInfo } from "./analytics-metrics.js";
3
3
  export { analyticsGroups, type GroupByInfo } from "./analytics-groups.js";
4
+ export { createDatasetSchema } from "./create-dataset.js";
@@ -0,0 +1,12 @@
1
+ import { archiveSuite as apiArchiveSuite } from "../langwatch-api-suites.js";
2
+
3
+ /**
4
+ * Handles the platform_archive_suite MCP tool invocation.
5
+ */
6
+ export async function handleArchiveSuite(params: {
7
+ id: string;
8
+ }): Promise<string> {
9
+ const result = await apiArchiveSuite(params.id);
10
+
11
+ return `Suite ${result.id} has been archived (soft-deleted).`;
12
+ }
@@ -0,0 +1,16 @@
1
+ import { assignPromptTag as apiAssignPromptTag } from "../langwatch-api.js";
2
+
3
+ export async function handleAssignPromptTag(params: {
4
+ idOrHandle: string;
5
+ tag: string;
6
+ versionId: string;
7
+ }): Promise<string> {
8
+ await apiAssignPromptTag({ idOrHandle: params.idOrHandle, tag: params.tag, versionId: params.versionId });
9
+
10
+ const lines: string[] = [];
11
+ lines.push("Tag assigned successfully!\n");
12
+ lines.push(`**Prompt**: ${params.idOrHandle}`);
13
+ lines.push(`**Tag**: ${params.tag}`);
14
+ lines.push(`**Version ID**: ${params.versionId}`);
15
+ return lines.join("\n");
16
+ }
@@ -0,0 +1,15 @@
1
+ import { createAgent as apiCreateAgent } from "../langwatch-api-agents.js";
2
+
3
+ export async function handleCreateAgent(params: {
4
+ name: string;
5
+ type: string;
6
+ config?: Record<string, unknown>;
7
+ }): Promise<string> {
8
+ const agent = await apiCreateAgent({
9
+ name: params.name,
10
+ type: params.type,
11
+ config: params.config ?? {},
12
+ });
13
+
14
+ return `Agent created successfully!\n\n**Name**: ${agent.name}\n**ID**: ${agent.id}\n**Type**: ${agent.type}`;
15
+ }
@@ -0,0 +1,18 @@
1
+ import { createAnnotation as apiCreateAnnotation } from "../langwatch-api-annotations.js";
2
+
3
+ export async function handleCreateAnnotation(params: {
4
+ traceId: string;
5
+ comment?: string;
6
+ isThumbsUp?: boolean;
7
+ email?: string;
8
+ }): Promise<string> {
9
+ const annotation = await apiCreateAnnotation(params.traceId, {
10
+ comment: params.comment,
11
+ isThumbsUp: params.isThumbsUp,
12
+ email: params.email,
13
+ });
14
+
15
+ const rating = params.isThumbsUp === true ? " 👍" : params.isThumbsUp === false ? " 👎" : "";
16
+
17
+ return `Annotation created successfully!${rating}\n\n**ID**: ${annotation.id ?? "—"}\n**Trace ID**: ${params.traceId}${params.comment ? `\n**Comment**: ${params.comment}` : ""}`;
18
+ }
@@ -0,0 +1,7 @@
1
+ import { createDashboard as apiCreateDashboard } from "../langwatch-api-dashboards.js";
2
+
3
+ export async function handleCreateDashboard(params: { name: string }): Promise<string> {
4
+ const dashboard = await apiCreateDashboard({ name: params.name });
5
+
6
+ return `Dashboard created successfully!\n\n**Name**: ${dashboard.name}\n**ID**: ${dashboard.id}`;
7
+ }
@@ -0,0 +1,23 @@
1
+ import { createDatasetRecords as apiCreateDatasetRecords } from "../langwatch-api-datasets.js";
2
+
3
+ /**
4
+ * Handles the platform_create_dataset_records MCP tool invocation.
5
+ *
6
+ * Creates records in a dataset in batch and returns a confirmation
7
+ * with the count of records created.
8
+ */
9
+ export async function handleCreateDatasetRecords(params: {
10
+ slugOrId: string;
11
+ entries: Record<string, unknown>[];
12
+ }): Promise<string> {
13
+ const result = await apiCreateDatasetRecords(params);
14
+ const count = Array.isArray(result.data) ? result.data.length : 0;
15
+
16
+ const lines: string[] = [];
17
+ lines.push(`${count} record(s) created successfully!\n`);
18
+ lines.push(
19
+ "> Use `platform_get_dataset` to see the updated dataset with all records.",
20
+ );
21
+
22
+ return lines.join("\n");
23
+ }
@@ -0,0 +1,22 @@
1
+ import { createDataset as apiCreateDataset } from "../langwatch-api-datasets.js";
2
+ import type { DatasetColumnType } from "../langwatch-api-datasets.js";
3
+ import { formatDatasetMutationDetails } from "./format-dataset-mutation.js";
4
+
5
+ /**
6
+ * Handles the platform_create_dataset MCP tool invocation.
7
+ *
8
+ * Creates a new dataset in the LangWatch project and returns a
9
+ * confirmation with the created dataset's details.
10
+ */
11
+ export async function handleCreateDataset(params: {
12
+ name: string;
13
+ columnTypes?: DatasetColumnType[];
14
+ }): Promise<string> {
15
+ const result = await apiCreateDataset(params);
16
+
17
+ const lines: string[] = [];
18
+ lines.push("Dataset created successfully!\n");
19
+ lines.push(...formatDatasetMutationDetails(result));
20
+
21
+ return lines.join("\n");
22
+ }
@@ -0,0 +1,12 @@
1
+ import { createPromptTag as apiCreatePromptTag } from "../langwatch-api.js";
2
+
3
+ export async function handleCreatePromptTag(params: {
4
+ name: string;
5
+ }): Promise<string> {
6
+ await apiCreatePromptTag(params.name);
7
+
8
+ const lines: string[] = [];
9
+ lines.push("Tag created successfully!\n");
10
+ lines.push(`**Name**: ${params.name}`);
11
+ return lines.join("\n");
12
+ }
@@ -27,6 +27,7 @@ export async function handleCreatePrompt(params: {
27
27
  handle?: string;
28
28
  messages: Array<{ role: string; content: string }>;
29
29
  model: string;
30
+ tags?: string[];
30
31
  }): Promise<string> {
31
32
  const handle = params.handle?.trim() || toHandle(params.name);
32
33
  if (!handle || !HANDLE_PATTERN.test(handle)) {
@@ -39,6 +40,7 @@ export async function handleCreatePrompt(params: {
39
40
  handle,
40
41
  messages: params.messages,
41
42
  model: params.model,
43
+ ...(params.tags ? { tags: params.tags } : {}),
42
44
  });
43
45
 
44
46
  const lines: string[] = [];
@@ -49,6 +51,8 @@ export async function handleCreatePrompt(params: {
49
51
  lines.push(`**Model**: ${params.model}`);
50
52
  if (result.latestVersionNumber != null)
51
53
  lines.push(`**Version**: v${result.latestVersionNumber}`);
54
+ if (params.tags && params.tags.length > 0)
55
+ lines.push(`**Tags**: ${params.tags.join(", ")}`);
52
56
 
53
57
  return lines.join("\n");
54
58
  }
@@ -0,0 +1,42 @@
1
+ import { createSuite as apiCreateSuite } from "../langwatch-api-suites.js";
2
+ import type { SuiteTarget } from "../langwatch-api-suites.js";
3
+
4
+ /**
5
+ * Handles the platform_create_suite MCP tool invocation.
6
+ */
7
+ export async function handleCreateSuite(params: {
8
+ name: string;
9
+ description?: string;
10
+ scenarioIds: string[];
11
+ targets: string;
12
+ repeatCount?: number;
13
+ labels?: string[];
14
+ }): Promise<string> {
15
+ let parsedTargets: SuiteTarget[];
16
+ try {
17
+ parsedTargets = JSON.parse(params.targets) as SuiteTarget[];
18
+ } catch {
19
+ return "Error: `targets` must be a valid JSON array of objects with `type` and `referenceId` fields.\n\nExample: [{\"type\": \"http\", \"referenceId\": \"agent_abc123\"}]";
20
+ }
21
+
22
+ const suite = await apiCreateSuite({
23
+ name: params.name,
24
+ description: params.description,
25
+ scenarioIds: params.scenarioIds,
26
+ targets: parsedTargets,
27
+ repeatCount: params.repeatCount,
28
+ labels: params.labels,
29
+ });
30
+
31
+ return [
32
+ `Suite "${suite.name}" created successfully.`,
33
+ "",
34
+ `**ID**: ${suite.id}`,
35
+ `**Slug**: ${suite.slug}`,
36
+ `**Scenarios**: ${suite.scenarioIds.length}`,
37
+ `**Targets**: ${suite.targets.length}`,
38
+ `**Repeat**: ${suite.repeatCount}x`,
39
+ "",
40
+ `> Use \`platform_run_suite\` with ID \`${suite.id}\` to trigger execution.`,
41
+ ].join("\n");
42
+ }
@@ -0,0 +1,7 @@
1
+ import { deleteAgent as apiDeleteAgent } from "../langwatch-api-agents.js";
2
+
3
+ export async function handleDeleteAgent(params: { id: string }): Promise<string> {
4
+ const result = await apiDeleteAgent(params.id);
5
+
6
+ return `Agent archived successfully!\n\n**Name**: ${result.name}\n**ID**: ${result.id}`;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { deleteAnnotation as apiDeleteAnnotation } from "../langwatch-api-annotations.js";
2
+
3
+ export async function handleDeleteAnnotation(params: { id: string }): Promise<string> {
4
+ await apiDeleteAnnotation(params.id);
5
+
6
+ return `Annotation deleted successfully!\n\n**ID**: ${params.id}`;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { deleteDashboard as apiDeleteDashboard } from "../langwatch-api-dashboards.js";
2
+
3
+ export async function handleDeleteDashboard(params: { id: string }): Promise<string> {
4
+ const result = await apiDeleteDashboard(params.id);
5
+
6
+ return `Dashboard deleted successfully!\n\n**Name**: ${result.name}\n**ID**: ${result.id}`;
7
+ }
@@ -0,0 +1,22 @@
1
+ import { deleteDatasetRecords as apiDeleteDatasetRecords } from "../langwatch-api-datasets.js";
2
+
3
+ /**
4
+ * Handles the platform_delete_dataset_records MCP tool invocation.
5
+ *
6
+ * Deletes records from a dataset by IDs and returns confirmation
7
+ * with the count of records deleted.
8
+ */
9
+ export async function handleDeleteDatasetRecords(params: {
10
+ slugOrId: string;
11
+ recordIds: string[];
12
+ }): Promise<string> {
13
+ const result = await apiDeleteDatasetRecords(params);
14
+
15
+ const lines: string[] = [];
16
+ lines.push(`${result.deletedCount} record(s) deleted successfully!\n`);
17
+ lines.push(
18
+ "> Use `platform_get_dataset` to see the updated dataset.",
19
+ );
20
+
21
+ return lines.join("\n");
22
+ }
@@ -0,0 +1,20 @@
1
+ import { deleteDataset as apiDeleteDataset } from "../langwatch-api-datasets.js";
2
+
3
+ /**
4
+ * Handles the platform_delete_dataset MCP tool invocation.
5
+ *
6
+ * Archives (soft-deletes) a dataset and returns confirmation.
7
+ */
8
+ export async function handleDeleteDataset(params: {
9
+ slugOrId: string;
10
+ }): Promise<string> {
11
+ await apiDeleteDataset(params.slugOrId);
12
+
13
+ const lines: string[] = [];
14
+ lines.push("Dataset deleted successfully!\n");
15
+ lines.push(
16
+ "> The dataset has been archived and will no longer appear in listings.",
17
+ );
18
+
19
+ return lines.join("\n");
20
+ }
@@ -0,0 +1,12 @@
1
+ import { deleteEvaluator as apiDeleteEvaluator } from "../langwatch-api-evaluators.js";
2
+
3
+ /**
4
+ * Handles the platform_delete_evaluator MCP tool invocation.
5
+ */
6
+ export async function handleDeleteEvaluator(params: {
7
+ idOrSlug: string;
8
+ }): Promise<string> {
9
+ const result = await apiDeleteEvaluator(params.idOrSlug);
10
+
11
+ return `Evaluator ${result.id} has been archived (soft-deleted).`;
12
+ }
@@ -0,0 +1,12 @@
1
+ import { deletePromptTag as apiDeletePromptTag } from "../langwatch-api.js";
2
+
3
+ export async function handleDeletePromptTag(params: {
4
+ tag: string;
5
+ }): Promise<string> {
6
+ await apiDeletePromptTag(params.tag);
7
+
8
+ const lines: string[] = [];
9
+ lines.push("Tag deleted successfully!\n");
10
+ lines.push(`**Tag**: ${params.tag}`);
11
+ return lines.join("\n");
12
+ }