@langwatch/mcp-server 0.7.0 → 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.
- package/.release-please-shim +1 -0
- package/CHANGELOG.md +66 -0
- package/dist/{archive-scenario-WJ2A7ETN.js → archive-scenario-YKGLJ4MZ.js} +4 -4
- package/dist/{archive-suite-4JOM4SSL.js → archive-suite-QFNDO3Y3.js} +4 -4
- package/dist/{assign-prompt-tag-GL7EAAF3.js → assign-prompt-tag-Y2B4CBBT.js} +3 -3
- package/dist/{chunk-E5JYYU3J.js → chunk-B57MZ4WI.js} +89 -83
- package/dist/{chunk-CCWCIJJ3.js → chunk-CPUPGDNA.js} +2 -2
- package/dist/{chunk-LUMEZEHL.js → chunk-FBRKHHJV.js} +2 -2
- package/dist/{chunk-HYMIWO3U.js → chunk-HDJDFKZR.js} +2 -2
- package/dist/{chunk-BWWY5KEF.js → chunk-KOO5733S.js} +3 -2
- package/dist/{chunk-EUQDVOSU.js → chunk-KZNBCKWG.js} +2 -2
- package/dist/{chunk-IE4M5OGE.js → chunk-L6QENXYA.js} +2 -2
- package/dist/{chunk-2GT7IFWK.js → chunk-NACSR6B7.js} +2 -2
- package/dist/{chunk-WQG2DFHX.js → chunk-OVQF3D5R.js} +2 -2
- package/dist/{chunk-ZVS4UKN2.js → chunk-PO7FM7IX.js} +2 -2
- package/dist/{chunk-EGH5RPXM.js → chunk-PZUWCWOS.js} +2 -2
- package/dist/{chunk-2WPLXEKF.js → chunk-YH2IBTEL.js} +7 -3
- package/dist/{chunk-4AUB2BIA.js → chunk-YI3OG4PI.js} +3 -3
- package/dist/config.js +1 -1
- package/dist/{create-agent-MBOOT3XK.js → create-agent-YRSDH7P7.js} +4 -4
- package/dist/{create-annotation-XMV6A7ED.js → create-annotation-FYQNKMVJ.js} +4 -4
- package/dist/{create-dashboard-VRKLFVZJ.js → create-dashboard-CORBR4YQ.js} +4 -4
- package/dist/{create-dataset-7HQPZCRE.js → create-dataset-ZC63T6BB.js} +4 -4
- package/dist/{create-dataset-records-2NIVFYTV.js → create-dataset-records-ILVNVKVR.js} +4 -4
- package/dist/{create-evaluator-WYFRFLRC.js → create-evaluator-2AU3PXFB.js} +4 -4
- package/dist/create-mcp-server.js +2 -2
- package/dist/{create-prompt-IEN7O6JT.js → create-prompt-NKRJ47YY.js} +3 -3
- package/dist/{create-prompt-tag-CAEZ45VO.js → create-prompt-tag-S4JX3ULL.js} +3 -3
- package/dist/{create-scenario-6YHSMGLP.js → create-scenario-BPRF75KF.js} +4 -4
- package/dist/{create-suite-H5XOFDE5.js → create-suite-4YN7D6K2.js} +4 -4
- package/dist/{delete-agent-JKTNBWAA.js → delete-agent-Y72R2YQA.js} +4 -4
- package/dist/{delete-annotation-ACMDV6QO.js → delete-annotation-UHWDMHSH.js} +4 -4
- package/dist/{delete-dashboard-VJSR7CRU.js → delete-dashboard-LPWT36KN.js} +4 -4
- package/dist/{delete-dataset-RTTTWP4D.js → delete-dataset-GGPQRHKX.js} +4 -4
- package/dist/{delete-dataset-records-KNQTIPQK.js → delete-dataset-records-LTG5LT26.js} +4 -4
- package/dist/{delete-evaluator-7FVC5WM4.js → delete-evaluator-F7QLXDHU.js} +4 -4
- package/dist/{delete-prompt-tag-ZMZUAGFW.js → delete-prompt-tag-B5UKZL45.js} +3 -3
- package/dist/{delete-workflow-EYQ3T4RQ.js → delete-workflow-4DGUDIDE.js} +4 -4
- package/dist/{get-agent-E3QSTVKG.js → get-agent-YEVICUX4.js} +4 -4
- package/dist/{get-analytics-2OHV763I.js → get-analytics-3W5CMU3F.js} +3 -3
- package/dist/{get-dashboard-PC7JDHH6.js → get-dashboard-NCQHN6MW.js} +4 -4
- package/dist/{get-dataset-H5IK5FVU.js → get-dataset-KBK6PH36.js} +4 -4
- package/dist/{get-evaluator-UWVUPYTM.js → get-evaluator-QDUL5LXR.js} +4 -4
- package/dist/{get-prompt-WZUOLLQC.js → get-prompt-XCSSNRKR.js} +3 -3
- package/dist/{get-scenario-Q6LCNUYN.js → get-scenario-FNRKOY7E.js} +4 -4
- package/dist/{get-simulation-run-Z2XKO256.js → get-simulation-run-WOEKUF7K.js} +4 -4
- package/dist/{get-suite-BXK5TN7P.js → get-suite-U5AOD5TC.js} +4 -4
- package/dist/{get-trace-4EJAYVBG.js → get-trace-MUWEJM2Z.js} +3 -3
- package/dist/{get-workflow-O34QJLHD.js → get-workflow-SOA7MT7L.js} +4 -4
- package/dist/{http-server-ISHF7NJX.js → http-server-7DMOCB75.js} +3 -3
- package/dist/index.js +423 -241
- package/dist/{langwatch-api-annotations-ERBG27RF.js → langwatch-api-annotations-Q57NDUVR.js} +4 -4
- package/dist/{langwatch-api-dashboards-G6TR7VVO.js → langwatch-api-dashboards-VBWWXV3Y.js} +4 -4
- package/dist/{langwatch-api-monitors-WSXZLS2B.js → langwatch-api-monitors-L3IY7FDT.js} +3 -3
- package/dist/{langwatch-api-secrets-RR5DKG2X.js → langwatch-api-secrets-S5HHF3XR.js} +3 -3
- package/dist/{langwatch-api-triggers-2RTNSWQY.js → langwatch-api-triggers-ME33QE26.js} +3 -3
- package/dist/langwatch-api-workflows-4CJQAYP2.js +15 -0
- package/dist/{list-agents-AW3P6FJV.js → list-agents-3HGIBJFM.js} +4 -4
- package/dist/{list-annotations-QNCGWPQ3.js → list-annotations-KWXYVEPI.js} +4 -4
- package/dist/{list-dashboards-R7RK2IXL.js → list-dashboards-VQ2LH666.js} +4 -4
- package/dist/{list-dataset-records-WVCSQP7P.js → list-dataset-records-RNRGROJP.js} +4 -4
- package/dist/{list-datasets-KEXRLDEU.js → list-datasets-I4A2LT2S.js} +4 -4
- package/dist/{list-evaluators-7R2LB4JH.js → list-evaluators-AKKRJ5MX.js} +4 -4
- package/dist/{list-model-providers-OBYJCKBX.js → list-model-providers-DVFEHFHZ.js} +4 -4
- package/dist/{list-prompt-tags-6LY3ZPYI.js → list-prompt-tags-PL5OISUA.js} +3 -3
- package/dist/{list-prompts-VWEZ4CDE.js → list-prompts-7VTFWE2Z.js} +3 -3
- package/dist/{list-scenarios-TXD4W2ZJ.js → list-scenarios-5BZWZ6ZN.js} +4 -4
- package/dist/{list-simulation-runs-RHPOLMFI.js → list-simulation-runs-WCZ6RLPE.js} +4 -4
- package/dist/{list-suites-FSGBX27Z.js → list-suites-RRQ2JX5Y.js} +4 -4
- package/dist/{list-workflows-VRGEZ3EN.js → list-workflows-UQB5FCX5.js} +4 -4
- package/dist/{rename-prompt-tag-VOJJLX4M.js → rename-prompt-tag-TURD6KYU.js} +3 -3
- package/dist/{run-agent-KTCC7TB7.js → run-agent-BEJ4K4CM.js} +4 -4
- package/dist/{run-evaluation-2X3V3Q6L.js → run-evaluation-AJ7WZNQD.js} +3 -3
- package/dist/{run-suite-BTMHGI2D.js → run-suite-U7V432G2.js} +4 -4
- package/dist/{run-workflow-IGAYGKJL.js → run-workflow-5WX7DK5T.js} +4 -4
- package/dist/{search-traces-VYFUIMXH.js → search-traces-ZCHNOMTX.js} +3 -3
- package/dist/{set-model-provider-W5IUI326.js → set-model-provider-6CFHMCNE.js} +4 -4
- package/dist/{update-agent-4BB7EYLR.js → update-agent-UE6UWLZP.js} +4 -4
- package/dist/{update-dataset-CXBKZ4W3.js → update-dataset-4XQZZE4S.js} +4 -4
- package/dist/{update-dataset-record-HOHAMHXG.js → update-dataset-record-GNNM5TKM.js} +4 -4
- package/dist/{update-evaluator-IVOR6FTR.js → update-evaluator-LHVDXIZD.js} +4 -4
- package/dist/{update-prompt-OWQAKE7K.js → update-prompt-3XEHECJ7.js} +3 -3
- package/dist/{update-scenario-GDFVILPN.js → update-scenario-DFPREYCD.js} +4 -4
- package/dist/{update-suite-BXYUYSPT.js → update-suite-RATU5THO.js} +4 -4
- package/package.json +6 -6
- package/src/__tests__/all-tools.integration.test.ts +9 -0
- package/src/__tests__/datasets.integration.test.ts +17 -0
- package/src/__tests__/datasets.unit.test.ts +4 -0
- package/src/__tests__/scenario-tools.unit.test.ts +3 -0
- package/src/config.ts +2 -0
- package/src/langwatch-api.ts +5 -1
- package/uv.lock +188 -530
- package/Dockerfile +0 -22
- package/build.js +0 -12
- package/dist/archive-scenario-WJ2A7ETN.js.map +0 -1
- package/dist/archive-suite-4JOM4SSL.js.map +0 -1
- package/dist/assign-prompt-tag-GL7EAAF3.js.map +0 -1
- package/dist/chunk-2GT7IFWK.js.map +0 -1
- package/dist/chunk-2WPLXEKF.js.map +0 -1
- package/dist/chunk-4AUB2BIA.js.map +0 -1
- package/dist/chunk-BWWY5KEF.js.map +0 -1
- package/dist/chunk-CCWCIJJ3.js.map +0 -1
- package/dist/chunk-E5JYYU3J.js.map +0 -1
- package/dist/chunk-EGH5RPXM.js.map +0 -1
- package/dist/chunk-EUQDVOSU.js.map +0 -1
- package/dist/chunk-HYMIWO3U.js.map +0 -1
- package/dist/chunk-IE4M5OGE.js.map +0 -1
- package/dist/chunk-LUMEZEHL.js.map +0 -1
- package/dist/chunk-NUFPTHKU.js.map +0 -1
- package/dist/chunk-WQG2DFHX.js.map +0 -1
- package/dist/chunk-WVI5CJ6S.js.map +0 -1
- package/dist/chunk-ZVS4UKN2.js.map +0 -1
- package/dist/chunk-ZXKLPC2E.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/create-agent-MBOOT3XK.js.map +0 -1
- package/dist/create-annotation-XMV6A7ED.js.map +0 -1
- package/dist/create-dashboard-VRKLFVZJ.js.map +0 -1
- package/dist/create-dataset-7HQPZCRE.js.map +0 -1
- package/dist/create-dataset-records-2NIVFYTV.js.map +0 -1
- package/dist/create-evaluator-WYFRFLRC.js.map +0 -1
- package/dist/create-mcp-server.js.map +0 -1
- package/dist/create-prompt-IEN7O6JT.js.map +0 -1
- package/dist/create-prompt-tag-CAEZ45VO.js.map +0 -1
- package/dist/create-scenario-6YHSMGLP.js.map +0 -1
- package/dist/create-suite-H5XOFDE5.js.map +0 -1
- package/dist/delete-agent-JKTNBWAA.js.map +0 -1
- package/dist/delete-annotation-ACMDV6QO.js.map +0 -1
- package/dist/delete-dashboard-VJSR7CRU.js.map +0 -1
- package/dist/delete-dataset-RTTTWP4D.js.map +0 -1
- package/dist/delete-dataset-records-KNQTIPQK.js.map +0 -1
- package/dist/delete-evaluator-7FVC5WM4.js.map +0 -1
- package/dist/delete-prompt-tag-ZMZUAGFW.js.map +0 -1
- package/dist/delete-workflow-EYQ3T4RQ.js.map +0 -1
- package/dist/discover-evaluator-schema-H23XCLNE.js.map +0 -1
- package/dist/discover-scenario-schema-MEEEVND7.js.map +0 -1
- package/dist/discover-schema-3T52ORPB.js.map +0 -1
- package/dist/get-agent-E3QSTVKG.js.map +0 -1
- package/dist/get-analytics-2OHV763I.js.map +0 -1
- package/dist/get-dashboard-PC7JDHH6.js.map +0 -1
- package/dist/get-dataset-H5IK5FVU.js.map +0 -1
- package/dist/get-evaluator-UWVUPYTM.js.map +0 -1
- package/dist/get-prompt-WZUOLLQC.js.map +0 -1
- package/dist/get-scenario-Q6LCNUYN.js.map +0 -1
- package/dist/get-simulation-run-Z2XKO256.js.map +0 -1
- package/dist/get-suite-BXK5TN7P.js.map +0 -1
- package/dist/get-trace-4EJAYVBG.js.map +0 -1
- package/dist/get-workflow-O34QJLHD.js.map +0 -1
- package/dist/http-server-ISHF7NJX.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/langwatch-api-annotations-ERBG27RF.js.map +0 -1
- package/dist/langwatch-api-dashboards-G6TR7VVO.js.map +0 -1
- package/dist/langwatch-api-monitors-WSXZLS2B.js.map +0 -1
- package/dist/langwatch-api-secrets-RR5DKG2X.js.map +0 -1
- package/dist/langwatch-api-triggers-2RTNSWQY.js.map +0 -1
- package/dist/langwatch-api-workflows-VJRIIDZ7.js +0 -15
- package/dist/langwatch-api-workflows-VJRIIDZ7.js.map +0 -1
- package/dist/list-agents-AW3P6FJV.js.map +0 -1
- package/dist/list-annotations-QNCGWPQ3.js.map +0 -1
- package/dist/list-dashboards-R7RK2IXL.js.map +0 -1
- package/dist/list-dataset-records-WVCSQP7P.js.map +0 -1
- package/dist/list-datasets-KEXRLDEU.js.map +0 -1
- package/dist/list-evaluators-7R2LB4JH.js.map +0 -1
- package/dist/list-model-providers-OBYJCKBX.js.map +0 -1
- package/dist/list-prompt-tags-6LY3ZPYI.js.map +0 -1
- package/dist/list-prompts-VWEZ4CDE.js.map +0 -1
- package/dist/list-scenarios-TXD4W2ZJ.js.map +0 -1
- package/dist/list-simulation-runs-RHPOLMFI.js.map +0 -1
- package/dist/list-suites-FSGBX27Z.js.map +0 -1
- package/dist/list-workflows-VRGEZ3EN.js.map +0 -1
- package/dist/rename-prompt-tag-VOJJLX4M.js.map +0 -1
- package/dist/run-agent-KTCC7TB7.js.map +0 -1
- package/dist/run-evaluation-2X3V3Q6L.js.map +0 -1
- package/dist/run-suite-BTMHGI2D.js.map +0 -1
- package/dist/run-workflow-IGAYGKJL.js.map +0 -1
- package/dist/search-traces-VYFUIMXH.js.map +0 -1
- package/dist/set-model-provider-W5IUI326.js.map +0 -1
- package/dist/update-agent-4BB7EYLR.js.map +0 -1
- package/dist/update-dataset-CXBKZ4W3.js.map +0 -1
- package/dist/update-dataset-record-HOHAMHXG.js.map +0 -1
- package/dist/update-evaluator-IVOR6FTR.js.map +0 -1
- package/dist/update-prompt-OWQAKE7K.js.map +0 -1
- package/dist/update-scenario-GDFVILPN.js.map +0 -1
- package/dist/update-suite-BXYUYSPT.js.map +0 -1
- package/tests/evaluations.ipynb +0 -649
- package/tests/fixtures/azure/azure_openai_stream_bot_expected.py +0 -102
- package/tests/fixtures/azure/azure_openai_stream_bot_input.py +0 -78
- package/tests/fixtures/dspy/dspy_bot_expected.py +0 -61
- package/tests/fixtures/dspy/dspy_bot_input.py +0 -53
- package/tests/fixtures/fastapi/fastapi_app_expected.py +0 -68
- package/tests/fixtures/fastapi/fastapi_app_input.py +0 -60
- package/tests/fixtures/fastapi/prompt_management_fastapi_expected.py +0 -114
- package/tests/fixtures/fastapi/prompt_management_fastapi_input.py +0 -88
- package/tests/fixtures/haystack/haystack_bot_expected.py +0 -141
- package/tests/fixtures/haystack/haystack_bot_input.py +0 -69
- package/tests/fixtures/langchain/langchain_bot_expected.py +0 -53
- package/tests/fixtures/langchain/langchain_bot_input.py +0 -45
- package/tests/fixtures/langchain/langchain_bot_with_memory_expected.py +0 -69
- package/tests/fixtures/langchain/langchain_bot_with_memory_input.py +0 -61
- package/tests/fixtures/langchain/langchain_rag_bot_expected.py +0 -97
- package/tests/fixtures/langchain/langchain_rag_bot_input.py +0 -77
- package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_expected.py +0 -116
- package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_input.py +0 -81
- package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_expected.py +0 -331
- package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_input.py +0 -106
- package/tests/fixtures/litellm/litellm_bot_expected.py +0 -40
- package/tests/fixtures/litellm/litellm_bot_input.py +0 -35
- package/tests/fixtures/openai/openai_bot_expected.py +0 -43
- package/tests/fixtures/openai/openai_bot_function_call_expected.py +0 -91
- package/tests/fixtures/openai/openai_bot_function_call_input.py +0 -82
- package/tests/fixtures/openai/openai_bot_input.py +0 -36
- package/tests/fixtures/openai/openai_bot_rag_expected.py +0 -73
- package/tests/fixtures/openai/openai_bot_rag_input.py +0 -51
- package/tests/fixtures/opentelemetry/openinference_dspy_bot_expected.py +0 -63
- package/tests/fixtures/opentelemetry/openinference_dspy_bot_input.py +0 -58
- package/tests/fixtures/opentelemetry/openinference_langchain_bot_expected.py +0 -53
- package/tests/fixtures/opentelemetry/openinference_langchain_bot_input.py +0 -52
- package/tests/fixtures/opentelemetry/openinference_openai_bot_expected.py +0 -49
- package/tests/fixtures/opentelemetry/openinference_openai_bot_input.py +0 -41
- package/tests/fixtures/opentelemetry/openllmetry_openai_bot_expected.py +0 -44
- package/tests/fixtures/opentelemetry/openllmetry_openai_bot_input.py +0 -40
- package/tests/fixtures/strands/strands_bot_expected.py +0 -84
- package/tests/fixtures/strands/strands_bot_input.py +0 -52
- package/tests/scenario-openai.test.ts +0 -160
- package/tsup.config.ts +0 -14
- package/vitest.config.js +0 -7
|
@@ -781,6 +781,7 @@ describe("All MCP tools integration", () => {
|
|
|
781
781
|
// =====================
|
|
782
782
|
describe("discover_schema", () => {
|
|
783
783
|
describe("when category is filters", () => {
|
|
784
|
+
/** @scenario Agent discovers available filter fields */
|
|
784
785
|
it("returns filter field documentation", async () => {
|
|
785
786
|
const { formatSchema } = await import(
|
|
786
787
|
"../tools/discover-schema.js"
|
|
@@ -793,6 +794,7 @@ describe("All MCP tools integration", () => {
|
|
|
793
794
|
});
|
|
794
795
|
|
|
795
796
|
describe("when category is metrics", () => {
|
|
797
|
+
/** @scenario Agent discovers available metrics with allowed aggregations */
|
|
796
798
|
it("returns metric documentation", async () => {
|
|
797
799
|
const { formatSchema } = await import(
|
|
798
800
|
"../tools/discover-schema.js"
|
|
@@ -818,6 +820,7 @@ describe("All MCP tools integration", () => {
|
|
|
818
820
|
});
|
|
819
821
|
|
|
820
822
|
describe("when category is groups", () => {
|
|
823
|
+
/** @scenario Agent discovers available group-by options */
|
|
821
824
|
it("returns group-by options", async () => {
|
|
822
825
|
const { formatSchema } = await import(
|
|
823
826
|
"../tools/discover-schema.js"
|
|
@@ -876,6 +879,7 @@ describe("All MCP tools integration", () => {
|
|
|
876
879
|
});
|
|
877
880
|
|
|
878
881
|
describe("when category is all", () => {
|
|
882
|
+
/** @scenario Agent discovers all schema information at once */
|
|
879
883
|
it("returns all schema categories", async () => {
|
|
880
884
|
const { formatSchema } = await import(
|
|
881
885
|
"../tools/discover-schema.js"
|
|
@@ -895,6 +899,7 @@ describe("All MCP tools integration", () => {
|
|
|
895
899
|
// =====================
|
|
896
900
|
describe("search_traces", () => {
|
|
897
901
|
describe("when traces are found", () => {
|
|
902
|
+
/** @scenario Agent searches traces with a text query */
|
|
898
903
|
it("returns formatted trace digests", async () => {
|
|
899
904
|
const { handleSearchTraces } = await import(
|
|
900
905
|
"../tools/search-traces.js"
|
|
@@ -924,6 +929,7 @@ describe("All MCP tools integration", () => {
|
|
|
924
929
|
});
|
|
925
930
|
|
|
926
931
|
describe("when pagination token is present", () => {
|
|
932
|
+
/** @scenario Agent paginates through trace results */
|
|
927
933
|
it("includes scroll ID for next page", async () => {
|
|
928
934
|
const { handleSearchTraces } = await import(
|
|
929
935
|
"../tools/search-traces.js"
|
|
@@ -953,6 +959,7 @@ describe("All MCP tools integration", () => {
|
|
|
953
959
|
});
|
|
954
960
|
|
|
955
961
|
describe("when filters are applied", () => {
|
|
962
|
+
/** @scenario Agent searches traces filtered by user_id */
|
|
956
963
|
it("passes filters to the API", async () => {
|
|
957
964
|
const { handleSearchTraces } = await import(
|
|
958
965
|
"../tools/search-traces.js"
|
|
@@ -976,6 +983,7 @@ describe("All MCP tools integration", () => {
|
|
|
976
983
|
// =====================
|
|
977
984
|
describe("get_trace", () => {
|
|
978
985
|
describe("when trace exists", () => {
|
|
986
|
+
/** @scenario Agent gets a single trace by ID in AI-readable format */
|
|
979
987
|
it("returns formatted trace with metadata and evaluations", async () => {
|
|
980
988
|
const { handleGetTrace } = await import(
|
|
981
989
|
"../tools/get-trace.js"
|
|
@@ -993,6 +1001,7 @@ describe("All MCP tools integration", () => {
|
|
|
993
1001
|
});
|
|
994
1002
|
|
|
995
1003
|
describe("when trace does not exist", () => {
|
|
1004
|
+
/** @scenario Agent gets a trace that does not exist */
|
|
996
1005
|
it("propagates the 404 error", async () => {
|
|
997
1006
|
const { handleGetTrace } = await import(
|
|
998
1007
|
"../tools/get-trace.js"
|
|
@@ -305,6 +305,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
305
305
|
|
|
306
306
|
describe("platform_list_datasets", () => {
|
|
307
307
|
describe("when the project has datasets", () => {
|
|
308
|
+
/** @scenario "List datasets returns a formatted summary of all datasets" */
|
|
308
309
|
it("returns a formatted list showing both datasets with their names, slugs, and record counts", async () => {
|
|
309
310
|
const { handleListDatasets } = await import(
|
|
310
311
|
"../tools/list-datasets.js"
|
|
@@ -320,6 +321,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
320
321
|
});
|
|
321
322
|
|
|
322
323
|
describe("when the project has no datasets", () => {
|
|
324
|
+
/** @scenario "List datasets returns a helpful message when none exist" */
|
|
323
325
|
it("returns a helpful message indicating no datasets were found", async () => {
|
|
324
326
|
emptyListMode = true;
|
|
325
327
|
const { handleListDatasets } = await import(
|
|
@@ -356,6 +358,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
356
358
|
|
|
357
359
|
describe("platform_get_dataset", () => {
|
|
358
360
|
describe("when the dataset exists", () => {
|
|
361
|
+
/** @scenario "Get dataset by slug returns metadata and a preview of records" */
|
|
359
362
|
it("returns the dataset name, slug, and column definitions", async () => {
|
|
360
363
|
const { handleGetDataset } = await import(
|
|
361
364
|
"../tools/get-dataset.js"
|
|
@@ -388,6 +391,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
388
391
|
});
|
|
389
392
|
|
|
390
393
|
describe("when the dataset does not exist", () => {
|
|
394
|
+
/** @scenario "Get dataset with non-existent slug returns an error" */
|
|
391
395
|
it("propagates the 404 error", async () => {
|
|
392
396
|
const { handleGetDataset } = await import(
|
|
393
397
|
"../tools/get-dataset.js"
|
|
@@ -403,6 +407,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
403
407
|
|
|
404
408
|
describe("platform_create_dataset", () => {
|
|
405
409
|
describe("when creating with name and columns", () => {
|
|
410
|
+
/** @scenario "Create a dataset with name and columns" */
|
|
406
411
|
it("returns confirmation including the generated slug", async () => {
|
|
407
412
|
const { handleCreateDataset } = await import(
|
|
408
413
|
"../tools/create-dataset.js"
|
|
@@ -420,6 +425,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
420
425
|
});
|
|
421
426
|
|
|
422
427
|
describe("when creating with only a name", () => {
|
|
428
|
+
/** @scenario "Create a dataset with only a name and no columns" */
|
|
423
429
|
it("returns confirmation including the slug", async () => {
|
|
424
430
|
const { handleCreateDataset } = await import(
|
|
425
431
|
"../tools/create-dataset.js"
|
|
@@ -437,6 +443,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
437
443
|
|
|
438
444
|
describe("platform_update_dataset", () => {
|
|
439
445
|
describe("when updating the dataset name", () => {
|
|
446
|
+
/** @scenario "Update a dataset name" */
|
|
440
447
|
it("returns confirmation reflecting the new name", async () => {
|
|
441
448
|
const { handleUpdateDataset } = await import(
|
|
442
449
|
"../tools/update-dataset.js"
|
|
@@ -451,6 +458,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
451
458
|
});
|
|
452
459
|
|
|
453
460
|
describe("when updating dataset column types", () => {
|
|
461
|
+
/** @scenario "Update a dataset column types" */
|
|
454
462
|
it("returns confirmation reflecting the new columns", async () => {
|
|
455
463
|
const { handleUpdateDataset } = await import(
|
|
456
464
|
"../tools/update-dataset.js"
|
|
@@ -465,6 +473,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
465
473
|
});
|
|
466
474
|
|
|
467
475
|
describe("when the dataset does not exist", () => {
|
|
476
|
+
/** @scenario "Update a non-existent dataset returns an error" */
|
|
468
477
|
it("propagates the 404 error", async () => {
|
|
469
478
|
const { handleUpdateDataset } = await import(
|
|
470
479
|
"../tools/update-dataset.js"
|
|
@@ -480,6 +489,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
480
489
|
|
|
481
490
|
describe("platform_delete_dataset", () => {
|
|
482
491
|
describe("when the dataset exists", () => {
|
|
492
|
+
/** @scenario "Delete a dataset archives it" */
|
|
483
493
|
it("returns confirmation that the dataset was deleted", async () => {
|
|
484
494
|
const { handleDeleteDataset } = await import(
|
|
485
495
|
"../tools/delete-dataset.js"
|
|
@@ -490,6 +500,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
490
500
|
});
|
|
491
501
|
|
|
492
502
|
describe("when the dataset does not exist", () => {
|
|
503
|
+
/** @scenario "Delete a non-existent dataset returns an error" */
|
|
493
504
|
it("propagates the 404 error", async () => {
|
|
494
505
|
const { handleDeleteDataset } = await import(
|
|
495
506
|
"../tools/delete-dataset.js"
|
|
@@ -505,6 +516,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
505
516
|
|
|
506
517
|
describe("platform_create_dataset_records", () => {
|
|
507
518
|
describe("when the dataset exists", () => {
|
|
519
|
+
/** @scenario "Add records to a dataset" */
|
|
508
520
|
it("returns confirmation with the count of records created", async () => {
|
|
509
521
|
const { handleCreateDatasetRecords } = await import(
|
|
510
522
|
"../tools/create-dataset-records.js"
|
|
@@ -522,6 +534,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
522
534
|
});
|
|
523
535
|
|
|
524
536
|
describe("when the dataset does not exist", () => {
|
|
537
|
+
/** @scenario "Add records to a non-existent dataset returns an error" */
|
|
525
538
|
it("propagates the 404 error", async () => {
|
|
526
539
|
const { handleCreateDatasetRecords } = await import(
|
|
527
540
|
"../tools/create-dataset-records.js"
|
|
@@ -540,6 +553,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
540
553
|
|
|
541
554
|
describe("platform_update_dataset_record", () => {
|
|
542
555
|
describe("when the record exists", () => {
|
|
556
|
+
/** @scenario "Update a single record entry" */
|
|
543
557
|
it("returns confirmation that the record was updated", async () => {
|
|
544
558
|
const { handleUpdateDatasetRecord } = await import(
|
|
545
559
|
"../tools/update-dataset-record.js"
|
|
@@ -554,6 +568,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
554
568
|
});
|
|
555
569
|
|
|
556
570
|
describe("when the dataset does not exist", () => {
|
|
571
|
+
/** @scenario "Update a record in a non-existent dataset returns an error" */
|
|
557
572
|
it("propagates the 404 error", async () => {
|
|
558
573
|
const { handleUpdateDatasetRecord } = await import(
|
|
559
574
|
"../tools/update-dataset-record.js"
|
|
@@ -573,6 +588,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
573
588
|
|
|
574
589
|
describe("platform_delete_dataset_records", () => {
|
|
575
590
|
describe("when the dataset exists", () => {
|
|
591
|
+
/** @scenario "Delete records by IDs" */
|
|
576
592
|
it("returns confirmation with the count of records deleted", async () => {
|
|
577
593
|
const { handleDeleteDatasetRecords } = await import(
|
|
578
594
|
"../tools/delete-dataset-records.js"
|
|
@@ -587,6 +603,7 @@ describe("MCP dataset tools integration", () => {
|
|
|
587
603
|
});
|
|
588
604
|
|
|
589
605
|
describe("when the dataset does not exist", () => {
|
|
606
|
+
/** @scenario "Delete records from a non-existent dataset returns an error" */
|
|
590
607
|
it("propagates the 404 error", async () => {
|
|
591
608
|
const { handleDeleteDatasetRecords } = await import(
|
|
592
609
|
"../tools/delete-dataset-records.js"
|
|
@@ -53,6 +53,7 @@ describe("formatDatasetResponse()", () => {
|
|
|
53
53
|
expect(result).toContain("my-dataset");
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
+
/** @scenario "formatDatasetResponse renders column table and record entries as markdown" */
|
|
56
57
|
it("includes a column table", () => {
|
|
57
58
|
expect(result).toContain("input");
|
|
58
59
|
expect(result).toContain("output");
|
|
@@ -171,6 +172,7 @@ describe("handleGetDataset()", () => {
|
|
|
171
172
|
|
|
172
173
|
describe("platform_create_dataset schema", () => {
|
|
173
174
|
describe("when input has no name", () => {
|
|
175
|
+
/** @scenario "platform_create_dataset schema rejects input without a name" */
|
|
174
176
|
it("rejects the input with a validation error", () => {
|
|
175
177
|
const result = createDatasetSchema.safeParse({});
|
|
176
178
|
expect(result.success).toBe(false);
|
|
@@ -196,6 +198,7 @@ describe("platform_create_dataset schema", () => {
|
|
|
196
198
|
|
|
197
199
|
describe("MCP server dataset tool registration", () => {
|
|
198
200
|
describe("when the MCP server is created", () => {
|
|
201
|
+
/** @scenario "All dataset tools are registered in the MCP server" */
|
|
199
202
|
it("registers all 8 dataset tools", async () => {
|
|
200
203
|
const { createMcpServer } = await import("../create-mcp-server.js");
|
|
201
204
|
const server = createMcpServer();
|
|
@@ -219,6 +222,7 @@ describe("MCP server dataset tool registration", () => {
|
|
|
219
222
|
|
|
220
223
|
describe("dataset tools API key requirement", () => {
|
|
221
224
|
describe("when no API key is configured", () => {
|
|
225
|
+
/** @scenario "Dataset tools require an API key" */
|
|
222
226
|
it("requireApiKey throws when apiKey is empty", async () => {
|
|
223
227
|
const savedKey = process.env.LANGWATCH_API_KEY;
|
|
224
228
|
delete process.env.LANGWATCH_API_KEY;
|
|
@@ -79,6 +79,7 @@ describe("handleListScenarios()", () => {
|
|
|
79
79
|
expect(result).toContain("scen_def456");
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
+
/** @scenario Agent lists all scenarios in a project */
|
|
82
83
|
it("includes the total count header", () => {
|
|
83
84
|
expect(result).toContain("# Scenarios (2 total)");
|
|
84
85
|
});
|
|
@@ -92,6 +93,7 @@ describe("handleListScenarios()", () => {
|
|
|
92
93
|
result = await handleListScenarios({});
|
|
93
94
|
});
|
|
94
95
|
|
|
96
|
+
/** @scenario Agent lists scenarios when none exist */
|
|
95
97
|
it("returns a no-scenarios message", () => {
|
|
96
98
|
expect(result).toContain("No scenarios found");
|
|
97
99
|
});
|
|
@@ -130,6 +132,7 @@ describe("handleGetScenario()", () => {
|
|
|
130
132
|
result = await handleGetScenario({ scenarioId: "scen_abc123" });
|
|
131
133
|
});
|
|
132
134
|
|
|
135
|
+
/** @scenario Agent gets full details of a scenario */
|
|
133
136
|
it("includes the scenario name in the heading", () => {
|
|
134
137
|
expect(result).toContain("# Scenario: Login Flow Happy Path");
|
|
135
138
|
});
|
package/src/config.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
3
3
|
export interface McpConfig {
|
|
4
4
|
apiKey: string | undefined;
|
|
5
5
|
endpoint: string;
|
|
6
|
+
projectId?: string;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
@@ -56,6 +57,7 @@ export function initConfig(args: { apiKey?: string; endpoint?: string }): void {
|
|
|
56
57
|
args.endpoint ||
|
|
57
58
|
process.env.LANGWATCH_ENDPOINT ||
|
|
58
59
|
"https://app.langwatch.ai",
|
|
60
|
+
projectId: process.env.LANGWATCH_PROJECT_ID,
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
63
|
|
package/src/langwatch-api.ts
CHANGED
|
@@ -118,10 +118,14 @@ export async function makeRequest(
|
|
|
118
118
|
path: string,
|
|
119
119
|
body?: unknown
|
|
120
120
|
): Promise<unknown> {
|
|
121
|
-
const
|
|
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";
|