@langwatch/mcp-server 0.10.0 → 1.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 (122) hide show
  1. package/.release-please-shim +1 -1
  2. package/CHANGELOG.md +62 -0
  3. package/README.md +9 -17
  4. package/dist/{archive-project-HZBRPR2S.js → archive-project-MK3673A7.js} +4 -3
  5. package/dist/{archive-scenario-P5RRITRM.js → archive-scenario-KATSXRIN.js} +4 -3
  6. package/dist/{archive-suite-NUUFD2EM.js → archive-suite-C3KX6IIZ.js} +4 -3
  7. package/dist/{assign-prompt-tag-FKCCZPML.js → assign-prompt-tag-E3C5W6PI.js} +3 -2
  8. package/dist/chunk-37SMPMQS.js +12 -0
  9. package/dist/{chunk-42ZHHHIJ.js → chunk-5UWY24RP.js} +79 -4
  10. package/dist/chunk-BJ7B4R26.js +42 -0
  11. package/dist/chunk-CE6QMZOP.js +432 -0
  12. package/dist/{chunk-X2SEURT2.js → chunk-DAIQKS27.js} +2 -2
  13. package/dist/{chunk-R7C7OUVG.js → chunk-EU22L52K.js} +2 -2
  14. package/dist/{chunk-TROIWSEQ.js → chunk-J45SVWPR.js} +2 -2
  15. package/dist/{chunk-CCM4ZFGF.js → chunk-O3LWVN67.js} +2 -2
  16. package/dist/{chunk-BB7EOKHR.js → chunk-RYRB2YVJ.js} +2 -2
  17. package/dist/{chunk-HKY3GW45.js → chunk-T7WJVS2N.js} +2 -2
  18. package/dist/{chunk-JHOSVOHT.js → chunk-UXXA4D6K.js} +2 -2
  19. package/dist/{chunk-FVDAZ4XG.js → chunk-VYPSKRPN.js} +219 -137
  20. package/dist/{chunk-CHKCEZBP.js → chunk-WDH5P5RF.js} +2 -2
  21. package/dist/{chunk-BBJ5WAJB.js → chunk-WWMDHZZV.js} +2 -2
  22. package/dist/{chunk-ADSJ2FDA.js → chunk-XY4STOBE.js} +2 -2
  23. package/dist/{chunk-BYWYM2RP.js → chunk-Y3HDZ6OW.js} +2 -2
  24. package/dist/config.js +1 -0
  25. package/dist/{create-agent-K5Q7BFGZ.js → create-agent-7W57J7MT.js} +4 -3
  26. package/dist/{create-annotation-KN3GE3DK.js → create-annotation-W2XELBCQ.js} +4 -3
  27. package/dist/{create-api-key-OQI5PUNQ.js → create-api-key-MKRXKFJM.js} +4 -3
  28. package/dist/{create-dashboard-G4QA5AXP.js → create-dashboard-QGL7IODC.js} +4 -3
  29. package/dist/{create-dataset-WQSC37N7.js → create-dataset-3PH7A4HG.js} +4 -3
  30. package/dist/{create-dataset-records-B4RL3FLC.js → create-dataset-records-4DZS3VRL.js} +4 -3
  31. package/dist/{create-evaluator-YFFQIR7E.js → create-evaluator-YWH6NC4M.js} +4 -3
  32. package/dist/create-mcp-server.js +3 -2
  33. package/dist/{create-project-CUVQ67VN.js → create-project-BOBQ32C5.js} +4 -3
  34. package/dist/{create-prompt-NGXKSP4X.js → create-prompt-FLCFGITE.js} +3 -2
  35. package/dist/{create-prompt-tag-IUKYPVHH.js → create-prompt-tag-EMPNIKEA.js} +3 -2
  36. package/dist/{create-scenario-FNBXALH3.js → create-scenario-BSBIHUL6.js} +4 -3
  37. package/dist/{create-suite-DJEPD4ZB.js → create-suite-TWF6BBR4.js} +4 -3
  38. package/dist/{delete-agent-TJI5XBBM.js → delete-agent-7MSYNY5E.js} +4 -3
  39. package/dist/{delete-annotation-KRP53TUU.js → delete-annotation-ZT5IGN24.js} +4 -3
  40. package/dist/{delete-dashboard-N5SZJIR3.js → delete-dashboard-BTIY5S3L.js} +4 -3
  41. package/dist/{delete-dataset-KDUOHL2P.js → delete-dataset-U45HQHPR.js} +4 -3
  42. package/dist/{delete-dataset-records-DM4W3PAW.js → delete-dataset-records-R43IMAWB.js} +4 -3
  43. package/dist/{delete-evaluator-7ZATLJOA.js → delete-evaluator-U6JMQ6C7.js} +4 -3
  44. package/dist/{delete-prompt-tag-I6HNMSVJ.js → delete-prompt-tag-4EV4TDHB.js} +3 -2
  45. package/dist/{delete-workflow-QEO74JQR.js → delete-workflow-5QYALXEL.js} +4 -3
  46. package/dist/discover-evaluator-schema-MRGHVNTT.js +2175 -0
  47. package/dist/{discover-scenario-schema-MEEEVND7.js → discover-scenario-schema-UPBTCWPG.js} +3 -1
  48. package/dist/{discover-schema-3T52ORPB.js → discover-schema-ICGXPHUW.js} +3 -1
  49. package/dist/{get-agent-3KDWCP5N.js → get-agent-7QJVPH72.js} +4 -3
  50. package/dist/{get-analytics-GPVJX7SF.js → get-analytics-PVERWOA5.js} +3 -2
  51. package/dist/{get-dashboard-YPTIE5YY.js → get-dashboard-ZZPC3WMD.js} +4 -3
  52. package/dist/{get-dataset-6DQFYITM.js → get-dataset-25TB2LQH.js} +4 -3
  53. package/dist/{get-evaluator-PCM6XQAU.js → get-evaluator-3FTRQKEC.js} +4 -3
  54. package/dist/{get-project-JCMWXVLU.js → get-project-5OAXYC57.js} +4 -3
  55. package/dist/{get-prompt-5XAGWWBG.js → get-prompt-I753LZKZ.js} +3 -2
  56. package/dist/{get-scenario-7XBCDZWX.js → get-scenario-DSSTR6FI.js} +4 -3
  57. package/dist/{get-simulation-run-AV24FJWI.js → get-simulation-run-RQPMS2MC.js} +4 -3
  58. package/dist/{get-suite-4DBVHFEM.js → get-suite-GTOCY5PL.js} +4 -3
  59. package/dist/{get-trace-MRBDS3HJ.js → get-trace-O5VT3NAC.js} +7 -9
  60. package/dist/{get-workflow-UR4Y6UFX.js → get-workflow-3EZDOEIF.js} +4 -3
  61. package/dist/http-server-2ACJ3CXW.js +24366 -0
  62. package/dist/index.js +23374 -3140
  63. package/dist/{langwatch-api-annotations-ZJDRB4JH.js → langwatch-api-annotations-E65MI3WZ.js} +4 -3
  64. package/dist/{langwatch-api-dashboards-WARLI6NF.js → langwatch-api-dashboards-QCDECRCY.js} +4 -3
  65. package/dist/{langwatch-api-monitors-4XKXHYCG.js → langwatch-api-monitors-UIO2KTDV.js} +3 -2
  66. package/dist/{langwatch-api-secrets-6SHK5G7Q.js → langwatch-api-secrets-4T2EKSJ7.js} +3 -2
  67. package/dist/{langwatch-api-triggers-5SX6R2WU.js → langwatch-api-triggers-MPOEKPUY.js} +3 -2
  68. package/dist/{langwatch-api-workflows-NLJENNXE.js → langwatch-api-workflows-5HRZ7HR4.js} +4 -3
  69. package/dist/{list-agents-NECO7MPI.js → list-agents-TIJTP566.js} +4 -3
  70. package/dist/{list-annotations-3OJEO774.js → list-annotations-CGX5BT7E.js} +4 -3
  71. package/dist/{list-api-keys-AWW7ROLB.js → list-api-keys-JLWJPFRX.js} +4 -3
  72. package/dist/{list-dashboards-DVPVVVKW.js → list-dashboards-RNIWX3TX.js} +4 -3
  73. package/dist/{list-dataset-records-I4BYORF5.js → list-dataset-records-B5MHZR66.js} +4 -3
  74. package/dist/{list-datasets-WUAE5HGX.js → list-datasets-BVCAMQCP.js} +4 -3
  75. package/dist/{list-evaluators-B6OSVAM2.js → list-evaluators-65FBTL2U.js} +4 -3
  76. package/dist/{list-model-providers-NL6IP4UZ.js → list-model-providers-GRK3I3VV.js} +4 -3
  77. package/dist/{list-projects-5FHMJ4PQ.js → list-projects-JLMBFMW3.js} +4 -3
  78. package/dist/{list-prompt-tags-Z2DD6FLQ.js → list-prompt-tags-UHNWDGQI.js} +3 -2
  79. package/dist/{list-prompts-VNXKHK7T.js → list-prompts-7254B3U7.js} +3 -2
  80. package/dist/{list-scenarios-CFZHXL76.js → list-scenarios-46YNICKM.js} +4 -3
  81. package/dist/{list-simulation-runs-AM2BXLBW.js → list-simulation-runs-LGNEFNPN.js} +4 -3
  82. package/dist/{list-suites-ZDOHAAXF.js → list-suites-5VK4HXEK.js} +4 -3
  83. package/dist/{list-workflows-WBRBKLIT.js → list-workflows-MLQDM6CP.js} +4 -3
  84. package/dist/{rename-prompt-tag-A4RJUK7Z.js → rename-prompt-tag-RHQMNEQL.js} +3 -2
  85. package/dist/report-issue-DXJ6TPTC.js +412 -0
  86. package/dist/{revoke-api-key-ZSPSPF5G.js → revoke-api-key-3Y35EMBT.js} +4 -3
  87. package/dist/{run-agent-JFNDY7MR.js → run-agent-RBSIFKRT.js} +4 -3
  88. package/dist/{run-suite-TH7LO5TJ.js → run-suite-K3DNQ3SE.js} +4 -3
  89. package/dist/{run-workflow-CK3JP5U2.js → run-workflow-5LVBZYLS.js} +4 -3
  90. package/dist/{search-traces-3BBVYPC3.js → search-traces-U4HLOCZ2.js} +9 -2
  91. package/dist/{set-model-provider-WOC5FNMV.js → set-model-provider-V3M5CDIY.js} +4 -3
  92. package/dist/{update-agent-YMEV5MTL.js → update-agent-47RZIHS7.js} +4 -3
  93. package/dist/{update-dataset-EYT5POFM.js → update-dataset-G6QJJGS5.js} +4 -3
  94. package/dist/{update-dataset-record-VFF5JTX4.js → update-dataset-record-RMWLSWCS.js} +4 -3
  95. package/dist/{update-evaluator-6IJHFG2E.js → update-evaluator-SFRRI5Q3.js} +4 -3
  96. package/dist/{update-project-OIT4WPFI.js → update-project-PI5DWBVK.js} +4 -3
  97. package/dist/{update-prompt-ZU2DD6KM.js → update-prompt-RQFTEO7Y.js} +3 -2
  98. package/dist/{update-scenario-3VUTPDRU.js → update-scenario-G3IU2UIB.js} +4 -3
  99. package/dist/{update-suite-C6JFDQHL.js → update-suite-TRGGLNR7.js} +4 -3
  100. package/package.json +20 -18
  101. package/pnpm-workspace.yaml +27 -2
  102. package/pyproject.toml +9 -1
  103. package/src/__tests__/all-tools.integration.test.ts +56 -120
  104. package/src/__tests__/documentation-fetch-security.integration.test.ts +176 -0
  105. package/src/__tests__/langwatch-api.unit.test.ts +206 -0
  106. package/src/__tests__/public-http-request-security.integration.test.ts +118 -0
  107. package/src/__tests__/report-issue.integration.test.ts +147 -0
  108. package/src/__tests__/tools.unit.test.ts +24 -0
  109. package/src/create-mcp-server.ts +43 -29
  110. package/src/documentation-fetch.ts +111 -0
  111. package/src/langwatch-api-agents.ts +2 -2
  112. package/src/langwatch-api.ts +138 -8
  113. package/src/public-http-request.ts +242 -0
  114. package/src/tools/get-trace.ts +2 -12
  115. package/src/tools/report-issue.ts +150 -0
  116. package/src/tools/search-traces.ts +4 -0
  117. package/src/utils/format-evaluations.ts +20 -0
  118. package/tsconfig.json +8 -1
  119. package/uv.lock +259 -205
  120. package/dist/chunk-XC62KJIT.js +0 -71
  121. package/dist/discover-evaluator-schema-H23XCLNE.js +0 -1402
  122. package/dist/http-server-XUQLIFE7.js +0 -226
@@ -1,226 +0,0 @@
1
- import {
2
- createMcpServer
3
- } from "./chunk-FVDAZ4XG.js";
4
- import "./chunk-42ZHHHIJ.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-XUQLIFE7.js.map