@langwatch/mcp-server 1.0.0 → 2.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 (125) hide show
  1. package/.python-version +1 -0
  2. package/CHANGELOG.md +21 -0
  3. package/CONTRIBUTING.md +1 -1
  4. package/README.md +55 -1
  5. package/dist/{archive-project-MK3673A7.js → archive-project-4EQGLBJJ.js} +5 -5
  6. package/dist/{archive-scenario-KATSXRIN.js → archive-scenario-W6BXYDZ3.js} +5 -5
  7. package/dist/{archive-suite-C3KX6IIZ.js → archive-suite-4T6BSRS7.js} +5 -5
  8. package/dist/{assign-prompt-tag-E3C5W6PI.js → assign-prompt-tag-VLXUWEKU.js} +4 -4
  9. package/dist/{chunk-VYPSKRPN.js → chunk-4QC7SA2L.js} +91 -91
  10. package/dist/{chunk-T7WJVS2N.js → chunk-5CCZFUXS.js} +2 -2
  11. package/dist/{chunk-J45SVWPR.js → chunk-77BNWQ3U.js} +2 -2
  12. package/dist/{chunk-XY4STOBE.js → chunk-7RHG56OH.js} +2 -2
  13. package/dist/{chunk-5UWY24RP.js → chunk-A2LEVYQ5.js} +2 -2
  14. package/dist/{chunk-UXXA4D6K.js → chunk-AQJO2EI5.js} +2 -2
  15. package/dist/{chunk-EU22L52K.js → chunk-CDYQOY5U.js} +2 -2
  16. package/dist/{chunk-O3LWVN67.js → chunk-J42FWRJ2.js} +2 -2
  17. package/dist/{chunk-BJ7B4R26.js → chunk-SAS5OB7F.js} +18 -2
  18. package/dist/{chunk-DAIQKS27.js → chunk-SFB4MU6H.js} +2 -2
  19. package/dist/{chunk-WWMDHZZV.js → chunk-TJCXFNDT.js} +2 -2
  20. package/dist/{chunk-CE6QMZOP.js → chunk-TOXJQDIZ.js} +4 -4
  21. package/dist/chunk-UJPXFA26.js +267 -0
  22. package/dist/{chunk-KOO5733S.js → chunk-WT4PO4A3.js} +8 -2
  23. package/dist/{chunk-RYRB2YVJ.js → chunk-YX3A3CFM.js} +2 -2
  24. package/dist/{chunk-WDH5P5RF.js → chunk-YZLYHLLI.js} +2 -2
  25. package/dist/{chunk-Y3HDZ6OW.js → chunk-ZWIL4EFL.js} +2 -2
  26. package/dist/config.js +2 -2
  27. package/dist/{create-agent-7W57J7MT.js → create-agent-7XHO6UIS.js} +5 -5
  28. package/dist/{create-annotation-W2XELBCQ.js → create-annotation-YQXRQC6A.js} +5 -5
  29. package/dist/{create-api-key-MKRXKFJM.js → create-api-key-YUS36KBU.js} +5 -5
  30. package/dist/{create-dashboard-QGL7IODC.js → create-dashboard-4Z5JO5LB.js} +5 -5
  31. package/dist/{create-dataset-3PH7A4HG.js → create-dataset-E6NMSVX7.js} +5 -5
  32. package/dist/{create-dataset-records-4DZS3VRL.js → create-dataset-records-SKHPRD2K.js} +5 -5
  33. package/dist/{create-evaluator-YWH6NC4M.js → create-evaluator-JXF5PF33.js} +5 -5
  34. package/dist/create-mcp-server.js +4 -4
  35. package/dist/{create-project-BOBQ32C5.js → create-project-CS2CB57Y.js} +5 -5
  36. package/dist/{create-prompt-FLCFGITE.js → create-prompt-F5RMX3L3.js} +4 -4
  37. package/dist/{create-prompt-tag-EMPNIKEA.js → create-prompt-tag-GMRWTEFR.js} +4 -4
  38. package/dist/{create-scenario-BSBIHUL6.js → create-scenario-JDR2VB2H.js} +5 -5
  39. package/dist/{create-suite-TWF6BBR4.js → create-suite-LZS6QIAF.js} +5 -5
  40. package/dist/{delete-agent-7MSYNY5E.js → delete-agent-O3EEH4S5.js} +5 -5
  41. package/dist/{delete-annotation-ZT5IGN24.js → delete-annotation-XP6FQM7A.js} +5 -5
  42. package/dist/{delete-dashboard-BTIY5S3L.js → delete-dashboard-RFUNYCNP.js} +5 -5
  43. package/dist/{delete-dataset-U45HQHPR.js → delete-dataset-3MJFRDLP.js} +5 -5
  44. package/dist/{delete-dataset-records-R43IMAWB.js → delete-dataset-records-WPMU5GL5.js} +5 -5
  45. package/dist/{delete-evaluator-U6JMQ6C7.js → delete-evaluator-33SP2JFX.js} +5 -5
  46. package/dist/{delete-prompt-tag-4EV4TDHB.js → delete-prompt-tag-KNMZVSPB.js} +4 -4
  47. package/dist/{delete-workflow-5QYALXEL.js → delete-workflow-3NUXO46U.js} +5 -5
  48. package/dist/{discover-evaluator-schema-MRGHVNTT.js → discover-evaluator-schema-XTAD4X7D.js} +52 -36
  49. package/dist/{discover-scenario-schema-UPBTCWPG.js → discover-scenario-schema-FE64QK2D.js} +2 -2
  50. package/dist/{discover-schema-ICGXPHUW.js → discover-schema-L6QDPON3.js} +2 -2
  51. package/dist/{get-agent-7QJVPH72.js → get-agent-Y7MWZ65F.js} +5 -5
  52. package/dist/{get-analytics-PVERWOA5.js → get-analytics-TETCSOK6.js} +4 -4
  53. package/dist/{get-dashboard-ZZPC3WMD.js → get-dashboard-KHBEGZGL.js} +5 -5
  54. package/dist/{get-dataset-25TB2LQH.js → get-dataset-RCMU5VAH.js} +5 -5
  55. package/dist/{get-evaluator-3FTRQKEC.js → get-evaluator-ADMKVWYZ.js} +5 -5
  56. package/dist/{get-project-5OAXYC57.js → get-project-RAK7URQJ.js} +5 -5
  57. package/dist/{get-prompt-I753LZKZ.js → get-prompt-OY5B7TRI.js} +4 -4
  58. package/dist/{get-scenario-DSSTR6FI.js → get-scenario-ZTAJJL5T.js} +5 -5
  59. package/dist/{get-simulation-run-RQPMS2MC.js → get-simulation-run-T2ZQWYH2.js} +5 -5
  60. package/dist/{get-suite-GTOCY5PL.js → get-suite-J7JVWO6O.js} +5 -5
  61. package/dist/{get-trace-O5VT3NAC.js → get-trace-K7U234Q4.js} +4 -4
  62. package/dist/{get-workflow-3EZDOEIF.js → get-workflow-L5L2PSK3.js} +5 -5
  63. package/dist/http-security-EU3CHTY7.js +26 -0
  64. package/dist/{http-server-2ACJ3CXW.js → http-server-YXHFPPGA.js} +1033 -693
  65. package/dist/index.js +3066 -2105
  66. package/dist/{langwatch-api-annotations-E65MI3WZ.js → langwatch-api-annotations-FDAS6NQ7.js} +5 -5
  67. package/dist/{langwatch-api-dashboards-QCDECRCY.js → langwatch-api-dashboards-JTVCS7ZJ.js} +5 -5
  68. package/dist/{langwatch-api-monitors-UIO2KTDV.js → langwatch-api-monitors-3J7UIQME.js} +4 -4
  69. package/dist/{langwatch-api-secrets-4T2EKSJ7.js → langwatch-api-secrets-BUBSNCNO.js} +4 -4
  70. package/dist/{langwatch-api-triggers-MPOEKPUY.js → langwatch-api-triggers-EDFUCJN6.js} +4 -4
  71. package/dist/langwatch-api-workflows-NBJX5KOG.js +16 -0
  72. package/dist/{list-agents-TIJTP566.js → list-agents-KFHKGPXV.js} +5 -5
  73. package/dist/{list-annotations-CGX5BT7E.js → list-annotations-ZTVP4EEL.js} +5 -5
  74. package/dist/{list-api-keys-JLWJPFRX.js → list-api-keys-CWD4UQT5.js} +5 -5
  75. package/dist/{list-dashboards-RNIWX3TX.js → list-dashboards-PWG6P6KR.js} +5 -5
  76. package/dist/{list-dataset-records-B5MHZR66.js → list-dataset-records-IOE7LQXS.js} +5 -5
  77. package/dist/{list-datasets-BVCAMQCP.js → list-datasets-ZT4JYUDT.js} +5 -5
  78. package/dist/{list-evaluators-65FBTL2U.js → list-evaluators-SJHC7VBH.js} +5 -5
  79. package/dist/{list-model-providers-GRK3I3VV.js → list-model-providers-PPD2WPD2.js} +5 -5
  80. package/dist/{list-projects-JLMBFMW3.js → list-projects-K7QAIX2I.js} +5 -5
  81. package/dist/{list-prompt-tags-UHNWDGQI.js → list-prompt-tags-FOO6TNHB.js} +4 -4
  82. package/dist/{list-prompts-7254B3U7.js → list-prompts-SC2HAUFG.js} +4 -4
  83. package/dist/{list-scenarios-46YNICKM.js → list-scenarios-F2WYNRIE.js} +5 -5
  84. package/dist/{list-simulation-runs-LGNEFNPN.js → list-simulation-runs-KF5THG5H.js} +5 -5
  85. package/dist/{list-suites-5VK4HXEK.js → list-suites-CRY4VWW6.js} +5 -5
  86. package/dist/{list-workflows-MLQDM6CP.js → list-workflows-QSJWURCK.js} +5 -5
  87. package/dist/{rename-prompt-tag-RHQMNEQL.js → rename-prompt-tag-EKWU5QF3.js} +4 -4
  88. package/dist/{report-issue-DXJ6TPTC.js → report-issue-XYVAPAYJ.js} +7 -7
  89. package/dist/{revoke-api-key-3Y35EMBT.js → revoke-api-key-FTRTZMOF.js} +5 -5
  90. package/dist/{run-agent-RBSIFKRT.js → run-agent-6SM4XNA7.js} +5 -5
  91. package/dist/{run-suite-K3DNQ3SE.js → run-suite-NKZCJ2IN.js} +5 -5
  92. package/dist/{run-workflow-5LVBZYLS.js → run-workflow-QPXC627O.js} +5 -5
  93. package/dist/{search-traces-U4HLOCZ2.js → search-traces-A6HFKPLJ.js} +4 -4
  94. package/dist/{set-model-provider-V3M5CDIY.js → set-model-provider-3WKT63ZN.js} +5 -5
  95. package/dist/{update-agent-47RZIHS7.js → update-agent-SMAEHLXH.js} +5 -5
  96. package/dist/{update-dataset-G6QJJGS5.js → update-dataset-BDUK7TUO.js} +5 -5
  97. package/dist/{update-dataset-record-RMWLSWCS.js → update-dataset-record-4ZSDRBSW.js} +5 -5
  98. package/dist/{update-evaluator-SFRRI5Q3.js → update-evaluator-LS6TIBY7.js} +5 -5
  99. package/dist/{update-project-PI5DWBVK.js → update-project-LKVYXENH.js} +5 -5
  100. package/dist/{update-prompt-RQFTEO7Y.js → update-prompt-ODCRQRN6.js} +4 -4
  101. package/dist/{update-scenario-G3IU2UIB.js → update-scenario-NEXCAQI7.js} +5 -5
  102. package/dist/{update-suite-TRGGLNR7.js → update-suite-SNO3GS7T.js} +5 -5
  103. package/package.json +3 -3
  104. package/pyproject.toml +1 -1
  105. package/src/__tests__/config.unit.test.ts +33 -0
  106. package/src/__tests__/docker.integration.test.ts +91 -7
  107. package/src/__tests__/documentation-fetch-security.integration.test.ts +8 -2
  108. package/src/__tests__/feature-map-tool-drift.unit.test.ts +93 -0
  109. package/src/__tests__/http-security-origin.unit.test.ts +97 -0
  110. package/src/__tests__/http-security-sessions.unit.test.ts +209 -0
  111. package/src/__tests__/http-security-verifier.unit.test.ts +248 -0
  112. package/src/__tests__/http-server-allocation.integration.test.ts +279 -0
  113. package/src/__tests__/http-server-origin.integration.test.ts +169 -0
  114. package/src/__tests__/http-server-session-auth.integration.test.ts +341 -0
  115. package/src/__tests__/http-transport.integration.test.ts +85 -87
  116. package/src/__tests__/support/http-server-harness.ts +138 -0
  117. package/src/config.ts +17 -2
  118. package/src/http-security.ts +492 -0
  119. package/src/http-server.ts +536 -152
  120. package/src/index.ts +49 -2
  121. package/src/tools/discover-evaluator-schema.ts +2 -2
  122. package/tsconfig.json +2 -2
  123. package/uv.lock +2 -2
  124. package/dist/langwatch-api-workflows-5HRZ7HR4.js +0 -16
  125. package/pnpm-workspace.yaml +0 -34
@@ -0,0 +1 @@
1
+ 3.11
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.0](https://github.com/langwatch/langwatch/compare/mcp-server@v1.0.0...mcp-server@v2.0.0) (2026-08-07)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * **mcp-server:** three behaviors change for callers of the HTTP server. A client that authenticated once at initialize and then sent only the session id must now send Authorization: Bearer <key> on every request. GET /sse?apiKey=<key> no longer authenticates; use the Authorization header. A deployment relying on the implicit 0.0.0.0 bind must pass --host 0.0.0.0, which the published container image already does.
9
+
10
+ ### Features
11
+
12
+ * **api-docs:** publish the REST API the SDKs actually call, and gate route coverage ([#6605](https://github.com/langwatch/langwatch/issues/6605)) ([25884bf](https://github.com/langwatch/langwatch/commit/25884bf3992eb99c00c3c7bafb09b979b02f0013))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **mcp-server:** authorize every request to the standalone HTTP server ([#6641](https://github.com/langwatch/langwatch/issues/6641)) ([af324de](https://github.com/langwatch/langwatch/commit/af324deeb3700f2745783a46e6fd5e8625ef868e))
18
+
19
+
20
+ ### Code Refactoring
21
+
22
+ * **build:** single pnpm workspace + restructure into sdks/ platform/ services/ mcp/ infra/ (ADR-076) ([#6405](https://github.com/langwatch/langwatch/issues/6405)) ([2bbeb7d](https://github.com/langwatch/langwatch/commit/2bbeb7dd2e0747e81478f22c3165adb9163c9f99))
23
+
3
24
  ## [1.0.0](https://github.com/langwatch/langwatch/compare/mcp-server@v0.10.1...mcp-server@v1.0.0) (2026-07-24)
4
25
 
5
26
 
package/CONTRIBUTING.md CHANGED
@@ -15,7 +15,7 @@ Thank you for your interest in contributing to the LangWatch MCP Server! This gu
15
15
  1. **Clone the repository and navigate to the MCP server directory:**
16
16
  ```bash
17
17
  git clone https://github.com/langwatch/langwatch.git
18
- cd langwatch/mcp-server
18
+ cd langwatch/mcp/typescript
19
19
  ```
20
20
 
21
21
  2. **Install dependencies and build the MCP server:**
package/README.md CHANGED
@@ -16,7 +16,7 @@ For Claude Code (manual) or other MCP clients (Cursor, Copilot, etc.), add an en
16
16
  - `args`: `-y`, then the package name `@langwatch/mcp-server` on a separate token
17
17
  - `env.LANGWATCH_API_KEY`: your LangWatch API key
18
18
 
19
- The API key is required for observability and prompt tools. Documentation tools work without it.
19
+ In stdio mode the API key is required for observability and prompt tools, and documentation tools work without it. In HTTP mode every MCP request needs a valid key, including documentation-tool requests, because the server authenticates the request before it reaches any tool.
20
20
 
21
21
  > The config is described in prose rather than as a JSON snippet because some CLI agents (notably Gemini CLI 0.36.0 and earlier) parse `@`-prefixed runs as file paths and can crash with `ENAMETOOLONG` when a multi-line JSON snippet wraps the scoped package name in double quotes. See [#3104](https://github.com/langwatch/langwatch/issues/3104). The bash form above is safe — the package name is followed by a whitespace terminator.
22
22
 
@@ -26,6 +26,60 @@ The API key is required for observability and prompt tools. Documentation tools
26
26
  |---------|---------|-------------|
27
27
  | `LANGWATCH_API_KEY` | `--apiKey` | API key for authentication |
28
28
  | `LANGWATCH_ENDPOINT` | `--endpoint` | API endpoint (default: `https://app.langwatch.ai`) |
29
+ | | `--http` | Serve over HTTP and SSE instead of stdio |
30
+ | | `--port` | HTTP port (default: `3000`) |
31
+ | `LANGWATCH_MCP_HTTP_HOST` | `--host` | HTTP listen address (default: `127.0.0.1`) |
32
+ | `LANGWATCH_MCP_ALLOWED_ORIGINS` | `--allowedOrigin` | Browser origins allowed to call the HTTP server |
33
+ | `LANGWATCH_MCP_TRUST_PROXY` | | Use `X-Forwarded-For` as the rate limit key (default: off) |
34
+
35
+ ### HTTP mode
36
+
37
+ In HTTP mode each client brings its own API key in an `Authorization: Bearer <key>`
38
+ header, on every MCP request rather than only at session start. That covers
39
+ `/mcp`, `/sse`, and `/messages`. The key is checked against the LangWatch API
40
+ before a session is created and re-checked on each request, so a session id by
41
+ itself grants no access and revoking a key stops its sessions being served
42
+ within a minute. The API key is never read from a query parameter.
43
+
44
+ Because authentication happens before routing, this applies to the documentation
45
+ tools too: unlike stdio mode, they are not reachable without a valid key.
46
+
47
+ Three routes do not take the bearer. `/health` reports liveness only.
48
+ `/.well-known/oauth-authorization-server` is the discovery document clients read
49
+ before they hold a token. `/oauth/token` exchanges an API key, sent as
50
+ `client_secret` in the form body, for a short-lived access token; it verifies
51
+ that key against the LangWatch API before issuing anything, and the token it
52
+ returns is what later MCP requests carry.
53
+
54
+ The server listens on `127.0.0.1` by default, per the MCP transport guidance for
55
+ local servers. Pass `--host 0.0.0.0` to accept connections from other machines,
56
+ and only behind a network boundary you trust.
57
+
58
+ Requests carrying a browser `Origin` header are checked against an allowlist.
59
+ Loopback origins are always allowed; anything else has to be listed:
60
+
61
+ ```bash
62
+ npx @langwatch/mcp-server --http --port 3000 \
63
+ --allowedOrigin https://your-app.example.com
64
+ ```
65
+
66
+ #### Running behind a proxy
67
+
68
+ Forwarded proxy headers resolve the external scheme that the OAuth metadata
69
+ document advertises, so they are read by default.
70
+
71
+ They do not decide the rate limit. Failed authentication is limited per client
72
+ address, and that address comes from the socket rather than from
73
+ `X-Forwarded-For`, so a client reaching the port directly cannot rotate a header
74
+ to reset its own counter. Behind a real proxy every request shares the proxy's
75
+ socket address, which means the whole proxy is limited as one client. Set
76
+ `LANGWATCH_MCP_TRUST_PROXY=true` there to limit per real client instead, and
77
+ only when the proxy overwrites `X-Forwarded-For` on the way in.
78
+
79
+ This is defense in depth, not the security boundary. API keys are verified
80
+ against the LangWatch API before a session is created and re-checked on every
81
+ request; the rate limit exists to make guessing expensive, not to decide who
82
+ gets in. A spoofable rate limit does not let anyone authenticate.
29
83
 
30
84
  ## Tools
31
85
 
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  archiveProject
3
- } from "./chunk-XY4STOBE.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-7RHG56OH.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/archive-project.ts
9
9
  async function handleArchiveProject(params) {
@@ -17,4 +17,4 @@ async function handleArchiveProject(params) {
17
17
  export {
18
18
  handleArchiveProject
19
19
  };
20
- //# sourceMappingURL=archive-project-MK3673A7.js.map
20
+ //# sourceMappingURL=archive-project-4EQGLBJJ.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  archiveScenario
3
- } from "./chunk-O3LWVN67.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-J42FWRJ2.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/archive-scenario.ts
9
9
  async function handleArchiveScenario(params) {
@@ -17,4 +17,4 @@ async function handleArchiveScenario(params) {
17
17
  export {
18
18
  handleArchiveScenario
19
19
  };
20
- //# sourceMappingURL=archive-scenario-KATSXRIN.js.map
20
+ //# sourceMappingURL=archive-scenario-W6BXYDZ3.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  archiveSuite
3
- } from "./chunk-WDH5P5RF.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-YZLYHLLI.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/archive-suite.ts
9
9
  async function handleArchiveSuite(params) {
@@ -13,4 +13,4 @@ async function handleArchiveSuite(params) {
13
13
  export {
14
14
  handleArchiveSuite
15
15
  };
16
- //# sourceMappingURL=archive-suite-C3KX6IIZ.js.map
16
+ //# sourceMappingURL=archive-suite-4T6BSRS7.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  assignPromptTag
3
- } from "./chunk-5UWY24RP.js";
4
- import "./chunk-KOO5733S.js";
5
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
+ import "./chunk-WT4PO4A3.js";
5
+ import "./chunk-SAS5OB7F.js";
6
6
 
7
7
  // src/tools/assign-prompt-tag.ts
8
8
  async function handleAssignPromptTag(params) {
@@ -17,4 +17,4 @@ async function handleAssignPromptTag(params) {
17
17
  export {
18
18
  handleAssignPromptTag
19
19
  };
20
- //# sourceMappingURL=assign-prompt-tag-E3C5W6PI.js.map
20
+ //# sourceMappingURL=assign-prompt-tag-VLXUWEKU.js.map