@langwatch/mcp-server 0.10.1 → 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 (144) hide show
  1. package/.python-version +1 -0
  2. package/.release-please-shim +1 -1
  3. package/CHANGELOG.md +75 -0
  4. package/CONTRIBUTING.md +1 -1
  5. package/README.md +64 -18
  6. package/dist/{archive-project-KAZFHR4A.js → archive-project-4EQGLBJJ.js} +5 -4
  7. package/dist/{archive-scenario-6M2IB7Y2.js → archive-scenario-W6BXYDZ3.js} +5 -4
  8. package/dist/{archive-suite-NXZ3YDS3.js → archive-suite-4T6BSRS7.js} +5 -4
  9. package/dist/{assign-prompt-tag-WPUJO55U.js → assign-prompt-tag-VLXUWEKU.js} +4 -3
  10. package/dist/chunk-37SMPMQS.js +12 -0
  11. package/dist/{chunk-HRFQAFPR.js → chunk-4QC7SA2L.js} +221 -134
  12. package/dist/{chunk-XRQNXN2Z.js → chunk-5CCZFUXS.js} +2 -2
  13. package/dist/{chunk-ITN2QGHF.js → chunk-77BNWQ3U.js} +2 -2
  14. package/dist/{chunk-B6UV3JVI.js → chunk-7RHG56OH.js} +2 -2
  15. package/dist/{chunk-CAY57CKF.js → chunk-A2LEVYQ5.js} +78 -5
  16. package/dist/{chunk-U2QIW2SW.js → chunk-AQJO2EI5.js} +2 -2
  17. package/dist/{chunk-GWEW5XON.js → chunk-CDYQOY5U.js} +2 -2
  18. package/dist/{chunk-LTEJDL4V.js → chunk-J42FWRJ2.js} +2 -2
  19. package/dist/chunk-SAS5OB7F.js +58 -0
  20. package/dist/{chunk-AGGE6NPR.js → chunk-SFB4MU6H.js} +2 -2
  21. package/dist/{chunk-COCNCXVJ.js → chunk-TJCXFNDT.js} +2 -2
  22. package/dist/chunk-TOXJQDIZ.js +432 -0
  23. package/dist/chunk-UJPXFA26.js +267 -0
  24. package/dist/{chunk-KOO5733S.js → chunk-WT4PO4A3.js} +8 -2
  25. package/dist/{chunk-RDUXCCFR.js → chunk-YX3A3CFM.js} +2 -2
  26. package/dist/{chunk-UKRCZJJC.js → chunk-YZLYHLLI.js} +2 -2
  27. package/dist/{chunk-ESGZVPPC.js → chunk-ZWIL4EFL.js} +2 -2
  28. package/dist/config.js +2 -1
  29. package/dist/{create-agent-BI7UTJ6A.js → create-agent-7XHO6UIS.js} +5 -4
  30. package/dist/{create-annotation-SNM2J6S4.js → create-annotation-YQXRQC6A.js} +5 -4
  31. package/dist/{create-api-key-23MXYC2L.js → create-api-key-YUS36KBU.js} +5 -4
  32. package/dist/{create-dashboard-CPOOOIKK.js → create-dashboard-4Z5JO5LB.js} +5 -4
  33. package/dist/{create-dataset-BVXPVVY2.js → create-dataset-E6NMSVX7.js} +5 -4
  34. package/dist/{create-dataset-records-S7VFIIMR.js → create-dataset-records-SKHPRD2K.js} +5 -4
  35. package/dist/{create-evaluator-WJAAQOUE.js → create-evaluator-JXF5PF33.js} +5 -4
  36. package/dist/create-mcp-server.js +4 -3
  37. package/dist/{create-project-BF7LMZH5.js → create-project-CS2CB57Y.js} +5 -4
  38. package/dist/{create-prompt-LZ3QHSU4.js → create-prompt-F5RMX3L3.js} +4 -3
  39. package/dist/{create-prompt-tag-IF4J24QM.js → create-prompt-tag-GMRWTEFR.js} +4 -3
  40. package/dist/{create-scenario-BK4E5DEU.js → create-scenario-JDR2VB2H.js} +5 -4
  41. package/dist/{create-suite-HEQPNLND.js → create-suite-LZS6QIAF.js} +5 -4
  42. package/dist/{delete-agent-Y4T2G5PT.js → delete-agent-O3EEH4S5.js} +5 -4
  43. package/dist/{delete-annotation-KYDMQTZG.js → delete-annotation-XP6FQM7A.js} +5 -4
  44. package/dist/{delete-dashboard-3RW647WJ.js → delete-dashboard-RFUNYCNP.js} +5 -4
  45. package/dist/{delete-dataset-SZAHFHHS.js → delete-dataset-3MJFRDLP.js} +5 -4
  46. package/dist/{delete-dataset-records-ISHKGEBH.js → delete-dataset-records-WPMU5GL5.js} +5 -4
  47. package/dist/{delete-evaluator-VKIG5I3S.js → delete-evaluator-33SP2JFX.js} +5 -4
  48. package/dist/{delete-prompt-tag-VYYL4GTF.js → delete-prompt-tag-KNMZVSPB.js} +4 -3
  49. package/dist/{delete-workflow-SHNPYSWQ.js → delete-workflow-3NUXO46U.js} +5 -4
  50. package/dist/discover-evaluator-schema-XTAD4X7D.js +2191 -0
  51. package/dist/{discover-scenario-schema-MEEEVND7.js → discover-scenario-schema-FE64QK2D.js} +3 -1
  52. package/dist/{discover-schema-3T52ORPB.js → discover-schema-L6QDPON3.js} +3 -1
  53. package/dist/{get-agent-IZSP7AR5.js → get-agent-Y7MWZ65F.js} +5 -4
  54. package/dist/{get-analytics-EDFAYYIQ.js → get-analytics-TETCSOK6.js} +4 -3
  55. package/dist/{get-dashboard-WSAO6IQ4.js → get-dashboard-KHBEGZGL.js} +5 -4
  56. package/dist/{get-dataset-BEVNXQNF.js → get-dataset-RCMU5VAH.js} +5 -4
  57. package/dist/{get-evaluator-HCVXNPZR.js → get-evaluator-ADMKVWYZ.js} +5 -4
  58. package/dist/{get-project-H4V3GYRQ.js → get-project-RAK7URQJ.js} +5 -4
  59. package/dist/{get-prompt-EWRJVVGB.js → get-prompt-OY5B7TRI.js} +4 -3
  60. package/dist/{get-scenario-24YUJS5W.js → get-scenario-ZTAJJL5T.js} +5 -4
  61. package/dist/{get-simulation-run-UX2W6F6I.js → get-simulation-run-T2ZQWYH2.js} +5 -4
  62. package/dist/{get-suite-B65ZKZJA.js → get-suite-J7JVWO6O.js} +5 -4
  63. package/dist/{get-trace-ZR7MIITH.js → get-trace-K7U234Q4.js} +8 -10
  64. package/dist/{get-workflow-YROHUQJW.js → get-workflow-L5L2PSK3.js} +5 -4
  65. package/dist/http-security-EU3CHTY7.js +26 -0
  66. package/dist/http-server-YXHFPPGA.js +24706 -0
  67. package/dist/index.js +23280 -3135
  68. package/dist/{langwatch-api-annotations-OPEXNTPF.js → langwatch-api-annotations-FDAS6NQ7.js} +5 -4
  69. package/dist/{langwatch-api-dashboards-NPQM6QJI.js → langwatch-api-dashboards-JTVCS7ZJ.js} +5 -4
  70. package/dist/{langwatch-api-monitors-3L25OOOS.js → langwatch-api-monitors-3J7UIQME.js} +4 -3
  71. package/dist/{langwatch-api-secrets-ZFURUA62.js → langwatch-api-secrets-BUBSNCNO.js} +4 -3
  72. package/dist/{langwatch-api-triggers-XGXXT7DD.js → langwatch-api-triggers-EDFUCJN6.js} +4 -3
  73. package/dist/langwatch-api-workflows-NBJX5KOG.js +16 -0
  74. package/dist/{list-agents-6ZNOV7FK.js → list-agents-KFHKGPXV.js} +5 -4
  75. package/dist/{list-annotations-6P3IWILH.js → list-annotations-ZTVP4EEL.js} +5 -4
  76. package/dist/{list-api-keys-JJI62KD2.js → list-api-keys-CWD4UQT5.js} +5 -4
  77. package/dist/{list-dashboards-G2WJOXWB.js → list-dashboards-PWG6P6KR.js} +5 -4
  78. package/dist/{list-dataset-records-GWWVOCII.js → list-dataset-records-IOE7LQXS.js} +5 -4
  79. package/dist/{list-datasets-HBTH33X4.js → list-datasets-ZT4JYUDT.js} +5 -4
  80. package/dist/{list-evaluators-K5OGB6TX.js → list-evaluators-SJHC7VBH.js} +5 -4
  81. package/dist/{list-model-providers-JMOGZLSO.js → list-model-providers-PPD2WPD2.js} +5 -4
  82. package/dist/{list-projects-OXJC2NW5.js → list-projects-K7QAIX2I.js} +5 -4
  83. package/dist/{list-prompt-tags-J2HPHVAZ.js → list-prompt-tags-FOO6TNHB.js} +4 -3
  84. package/dist/{list-prompts-C7GR72XL.js → list-prompts-SC2HAUFG.js} +4 -3
  85. package/dist/{list-scenarios-JEPGIIDO.js → list-scenarios-F2WYNRIE.js} +5 -4
  86. package/dist/{list-simulation-runs-DRSAGPEC.js → list-simulation-runs-KF5THG5H.js} +5 -4
  87. package/dist/{list-suites-POTZ3ZT6.js → list-suites-CRY4VWW6.js} +5 -4
  88. package/dist/{list-workflows-QQZQIOHB.js → list-workflows-QSJWURCK.js} +5 -4
  89. package/dist/{rename-prompt-tag-4AAV2BS4.js → rename-prompt-tag-EKWU5QF3.js} +4 -3
  90. package/dist/report-issue-XYVAPAYJ.js +412 -0
  91. package/dist/{revoke-api-key-TONB4ADQ.js → revoke-api-key-FTRTZMOF.js} +5 -4
  92. package/dist/{run-agent-7QE3YEH7.js → run-agent-6SM4XNA7.js} +5 -4
  93. package/dist/{run-suite-Q66OSPO4.js → run-suite-NKZCJ2IN.js} +5 -4
  94. package/dist/{run-workflow-RWX2D752.js → run-workflow-QPXC627O.js} +5 -4
  95. package/dist/{search-traces-M5E5VB4X.js → search-traces-A6HFKPLJ.js} +10 -3
  96. package/dist/{set-model-provider-XENT5D2P.js → set-model-provider-3WKT63ZN.js} +5 -4
  97. package/dist/{update-agent-GML25EE3.js → update-agent-SMAEHLXH.js} +5 -4
  98. package/dist/{update-dataset-R4MM6NNY.js → update-dataset-BDUK7TUO.js} +5 -4
  99. package/dist/{update-dataset-record-FN4BL5P4.js → update-dataset-record-4ZSDRBSW.js} +5 -4
  100. package/dist/{update-evaluator-LH2RDDB5.js → update-evaluator-LS6TIBY7.js} +5 -4
  101. package/dist/{update-project-H53IHRBB.js → update-project-LKVYXENH.js} +5 -4
  102. package/dist/{update-prompt-M33OTTAJ.js → update-prompt-ODCRQRN6.js} +4 -3
  103. package/dist/{update-scenario-FKTQRAFQ.js → update-scenario-NEXCAQI7.js} +5 -4
  104. package/dist/{update-suite-JJTNOTXN.js → update-suite-SNO3GS7T.js} +5 -4
  105. package/package.json +20 -18
  106. package/pyproject.toml +10 -2
  107. package/src/__tests__/all-tools.integration.test.ts +56 -120
  108. package/src/__tests__/config.unit.test.ts +33 -0
  109. package/src/__tests__/docker.integration.test.ts +91 -7
  110. package/src/__tests__/documentation-fetch-security.integration.test.ts +182 -0
  111. package/src/__tests__/feature-map-tool-drift.unit.test.ts +93 -0
  112. package/src/__tests__/http-security-origin.unit.test.ts +97 -0
  113. package/src/__tests__/http-security-sessions.unit.test.ts +209 -0
  114. package/src/__tests__/http-security-verifier.unit.test.ts +248 -0
  115. package/src/__tests__/http-server-allocation.integration.test.ts +279 -0
  116. package/src/__tests__/http-server-origin.integration.test.ts +169 -0
  117. package/src/__tests__/http-server-session-auth.integration.test.ts +341 -0
  118. package/src/__tests__/http-transport.integration.test.ts +85 -87
  119. package/src/__tests__/langwatch-api.unit.test.ts +206 -0
  120. package/src/__tests__/public-http-request-security.integration.test.ts +118 -0
  121. package/src/__tests__/report-issue.integration.test.ts +147 -0
  122. package/src/__tests__/support/http-server-harness.ts +138 -0
  123. package/src/__tests__/tools.unit.test.ts +24 -0
  124. package/src/config.ts +17 -2
  125. package/src/create-mcp-server.ts +43 -29
  126. package/src/documentation-fetch.ts +111 -0
  127. package/src/http-security.ts +492 -0
  128. package/src/http-server.ts +536 -152
  129. package/src/index.ts +49 -2
  130. package/src/langwatch-api-agents.ts +2 -2
  131. package/src/langwatch-api.ts +138 -8
  132. package/src/public-http-request.ts +242 -0
  133. package/src/tools/discover-evaluator-schema.ts +2 -2
  134. package/src/tools/get-trace.ts +2 -12
  135. package/src/tools/report-issue.ts +150 -0
  136. package/src/tools/search-traces.ts +4 -0
  137. package/src/utils/format-evaluations.ts +20 -0
  138. package/tsconfig.json +8 -1
  139. package/uv.lock +261 -207
  140. package/dist/chunk-IUP5IHBD.js +0 -71
  141. package/dist/discover-evaluator-schema-H23XCLNE.js +0 -1402
  142. package/dist/http-server-GXVEDA7G.js +0 -226
  143. package/dist/langwatch-api-workflows-CXCTTCXT.js +0 -15
  144. package/pnpm-workspace.yaml +0 -17
@@ -1,226 +0,0 @@
1
- import {
2
- createMcpServer
3
- } from "./chunk-HRFQAFPR.js";
4
- import "./chunk-CAY57CKF.js";
5
- import {
6
- getConfig,
7
- runWithConfig
8
- } from "./chunk-KOO5733S.js";
9
-
10
- // src/http-server.ts
11
- import express from "express";
12
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
13
- import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
14
- import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
15
- import { randomUUID, createHash } from "crypto";
16
- var oauthTokens = /* @__PURE__ */ new Map();
17
- function extractBearerToken(req) {
18
- const authHeader = req.headers.authorization;
19
- if (!authHeader?.startsWith("Bearer ")) return null;
20
- const token = authHeader.slice(7) || null;
21
- if (!token) return null;
22
- const oauthEntry = oauthTokens.get(token);
23
- if (oauthEntry) {
24
- if (Date.now() < oauthEntry.expiresAt) {
25
- return oauthEntry.apiKey;
26
- }
27
- oauthTokens.delete(token);
28
- return null;
29
- }
30
- return token;
31
- }
32
- function generateAccessToken() {
33
- return createHash("sha256").update(randomUUID()).digest("hex");
34
- }
35
- async function handleWithSessionConfig(apiKey, fn) {
36
- const baseConfig = getConfig();
37
- return runWithConfig({ ...baseConfig, apiKey }, fn);
38
- }
39
- async function startHttpServer({
40
- port
41
- }) {
42
- const app = express();
43
- app.set("trust proxy", true);
44
- app.use(express.json());
45
- app.use((_req, res, next) => {
46
- res.header("Access-Control-Allow-Origin", "*");
47
- res.header(
48
- "Access-Control-Allow-Methods",
49
- "GET, POST, DELETE, OPTIONS"
50
- );
51
- res.header(
52
- "Access-Control-Allow-Headers",
53
- "Content-Type, Authorization, mcp-session-id, MCP-Protocol-Version"
54
- );
55
- if (_req.method === "OPTIONS") {
56
- res.sendStatus(200);
57
- return;
58
- }
59
- next();
60
- });
61
- app.get("/health", (_req, res) => {
62
- res.json({ status: "ok" });
63
- });
64
- app.get(
65
- "/.well-known/oauth-authorization-server",
66
- (_req, res) => {
67
- const baseUrl = `${_req.protocol}://${_req.get("host")}`;
68
- res.json({
69
- issuer: baseUrl,
70
- token_endpoint: `${baseUrl}/oauth/token`,
71
- token_endpoint_auth_methods_supported: ["client_secret_post"],
72
- grant_types_supported: ["client_credentials"],
73
- response_types_supported: [],
74
- scopes_supported: ["mcp:tools"]
75
- });
76
- }
77
- );
78
- app.post(
79
- "/oauth/token",
80
- express.urlencoded({ extended: false }),
81
- (req, res) => {
82
- const grantType = req.body.grant_type;
83
- if (grantType !== "client_credentials") {
84
- res.status(400).json({
85
- error: "unsupported_grant_type",
86
- error_description: "Only client_credentials grant type is supported"
87
- });
88
- return;
89
- }
90
- const clientSecret = req.body.client_secret;
91
- if (!clientSecret || typeof clientSecret !== "string") {
92
- res.status(400).json({
93
- error: "invalid_request",
94
- error_description: "client_secret is required (use your LangWatch API key)"
95
- });
96
- return;
97
- }
98
- const expiresIn = 3600;
99
- const accessToken = generateAccessToken();
100
- oauthTokens.set(accessToken, {
101
- apiKey: clientSecret,
102
- expiresAt: Date.now() + expiresIn * 1e3
103
- });
104
- res.json({
105
- access_token: accessToken,
106
- token_type: "Bearer",
107
- expires_in: expiresIn,
108
- scope: "mcp:tools"
109
- });
110
- }
111
- );
112
- const sessions = {};
113
- app.post("/mcp", async (req, res) => {
114
- const sessionId = req.headers["mcp-session-id"];
115
- if (sessionId && sessions[sessionId]) {
116
- const session = sessions[sessionId];
117
- await handleWithSessionConfig(
118
- session.apiKey,
119
- () => session.transport.handleRequest(req, res, req.body)
120
- );
121
- return;
122
- }
123
- if (!sessionId && isInitializeRequest(req.body)) {
124
- const apiKey = extractBearerToken(req);
125
- if (!apiKey) {
126
- res.status(401).json({
127
- error: "Authorization: Bearer <LANGWATCH_API_KEY> header required"
128
- });
129
- return;
130
- }
131
- const transport = new StreamableHTTPServerTransport({
132
- sessionIdGenerator: () => randomUUID(),
133
- onsessioninitialized: (id) => {
134
- sessions[id] = { transport, apiKey };
135
- }
136
- });
137
- transport.onclose = () => {
138
- if (transport.sessionId) {
139
- delete sessions[transport.sessionId];
140
- }
141
- };
142
- const sessionServer = createMcpServer();
143
- await handleWithSessionConfig(
144
- apiKey,
145
- () => sessionServer.connect(transport)
146
- );
147
- await handleWithSessionConfig(
148
- apiKey,
149
- () => transport.handleRequest(req, res, req.body)
150
- );
151
- return;
152
- }
153
- res.status(400).json({
154
- error: "Invalid request \u2014 no session ID or not an initialize request"
155
- });
156
- });
157
- app.get("/mcp", async (req, res) => {
158
- const sessionId = req.headers["mcp-session-id"];
159
- if (sessionId && sessions[sessionId]) {
160
- const session = sessions[sessionId];
161
- await handleWithSessionConfig(
162
- session.apiKey,
163
- () => session.transport.handleRequest(req, res)
164
- );
165
- } else {
166
- res.status(400).json({ error: "Invalid request \u2014 no valid session ID" });
167
- }
168
- });
169
- app.delete("/mcp", async (req, res) => {
170
- const sessionId = req.headers["mcp-session-id"];
171
- if (sessionId && sessions[sessionId]) {
172
- const session = sessions[sessionId];
173
- await session.transport.close();
174
- delete sessions[sessionId];
175
- res.status(200).json({ status: "session closed" });
176
- } else {
177
- res.status(404).json({ error: "Session not found" });
178
- }
179
- });
180
- const sseSessions = {};
181
- app.get("/sse", async (req, res) => {
182
- const apiKey = extractBearerToken(req) || // lgtm[js/sensitive-get-query]
183
- req.query["apiKey"] || null;
184
- if (!apiKey) {
185
- res.status(401).json({
186
- error: "Authorization: Bearer <LANGWATCH_API_KEY> header or ?apiKey= query parameter required"
187
- });
188
- return;
189
- }
190
- const transport = new SSEServerTransport("/messages", res);
191
- sseSessions[transport.sessionId] = { transport, apiKey };
192
- const sessionServer = createMcpServer();
193
- res.on("close", () => {
194
- delete sseSessions[transport.sessionId];
195
- });
196
- await handleWithSessionConfig(
197
- apiKey,
198
- () => sessionServer.connect(transport)
199
- );
200
- });
201
- const handleSseMessage = async (req, res) => {
202
- const sessionId = req.query["sessionId"];
203
- if (!sessionId || !sseSessions[sessionId]) {
204
- res.status(400).json({ error: "Invalid or missing session ID" });
205
- return;
206
- }
207
- const session = sseSessions[sessionId];
208
- await handleWithSessionConfig(
209
- session.apiKey,
210
- () => session.transport.handlePostMessage(req, res, req.body)
211
- );
212
- };
213
- app.post("/messages", handleSseMessage);
214
- app.post("/sse/messages", handleSseMessage);
215
- return new Promise((resolve) => {
216
- const server = app.listen(port, "0.0.0.0", () => {
217
- const addr = server.address();
218
- const resolvedPort = typeof addr === "object" && addr ? addr.port : port;
219
- resolve({ server, port: resolvedPort });
220
- });
221
- });
222
- }
223
- export {
224
- startHttpServer
225
- };
226
- //# sourceMappingURL=http-server-GXVEDA7G.js.map
@@ -1,15 +0,0 @@
1
- import {
2
- deleteWorkflow,
3
- getWorkflow,
4
- listWorkflows,
5
- runWorkflow
6
- } from "./chunk-XRQNXN2Z.js";
7
- import "./chunk-CAY57CKF.js";
8
- import "./chunk-KOO5733S.js";
9
- export {
10
- deleteWorkflow,
11
- getWorkflow,
12
- listWorkflows,
13
- runWorkflow
14
- };
15
- //# sourceMappingURL=langwatch-api-workflows-CXCTTCXT.js.map
@@ -1,17 +0,0 @@
1
- minimumReleaseAge: 10080
2
-
3
- overrides:
4
- # Security: protobufjs code execution + prototype-pollution + DoS
5
- # (GHSA-xq3m-2v4x-88gg, GHSA-66ff-xgx4-vchm, GHSA-75px-5xx7-5xc7,
6
- # GHSA-jvwf-75h9-cwgg, GHSA-685m-2w69-288q)
7
- "protobufjs": ">=7.5.6 <8.0.0 || >=8.0.2"
8
- # Security: langsmith untrusted manifest deserialization (GHSA-3644-q5cj-c5c7).
9
- # langsmith is only a transitive of the @langwatch/scenario devDependency
10
- # (via langchain / @langchain/core); pinned to a known-safe version.
11
- "langsmith": "0.6.0"
12
- # Security: fast-uri path traversal + host confusion
13
- "fast-uri@<3.1.2": "3.1.2"
14
- liquidjs: ">=10.26.0"
15
-
16
- onlyBuiltDependencies:
17
- - node-pty