@langwatch/mcp-server 0.10.1 → 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.
- package/.release-please-shim +1 -1
- package/CHANGELOG.md +54 -0
- package/README.md +9 -17
- package/dist/{archive-project-KAZFHR4A.js → archive-project-MK3673A7.js} +4 -3
- package/dist/{archive-scenario-6M2IB7Y2.js → archive-scenario-KATSXRIN.js} +4 -3
- package/dist/{archive-suite-NXZ3YDS3.js → archive-suite-C3KX6IIZ.js} +4 -3
- package/dist/{assign-prompt-tag-WPUJO55U.js → assign-prompt-tag-E3C5W6PI.js} +3 -2
- package/dist/chunk-37SMPMQS.js +12 -0
- package/dist/{chunk-CAY57CKF.js → chunk-5UWY24RP.js} +77 -4
- package/dist/chunk-BJ7B4R26.js +42 -0
- package/dist/chunk-CE6QMZOP.js +432 -0
- package/dist/{chunk-AGGE6NPR.js → chunk-DAIQKS27.js} +2 -2
- package/dist/{chunk-GWEW5XON.js → chunk-EU22L52K.js} +2 -2
- package/dist/{chunk-ITN2QGHF.js → chunk-J45SVWPR.js} +2 -2
- package/dist/{chunk-LTEJDL4V.js → chunk-O3LWVN67.js} +2 -2
- package/dist/{chunk-RDUXCCFR.js → chunk-RYRB2YVJ.js} +2 -2
- package/dist/{chunk-XRQNXN2Z.js → chunk-T7WJVS2N.js} +2 -2
- package/dist/{chunk-U2QIW2SW.js → chunk-UXXA4D6K.js} +2 -2
- package/dist/{chunk-HRFQAFPR.js → chunk-VYPSKRPN.js} +220 -133
- package/dist/{chunk-UKRCZJJC.js → chunk-WDH5P5RF.js} +2 -2
- package/dist/{chunk-COCNCXVJ.js → chunk-WWMDHZZV.js} +2 -2
- package/dist/{chunk-B6UV3JVI.js → chunk-XY4STOBE.js} +2 -2
- package/dist/{chunk-ESGZVPPC.js → chunk-Y3HDZ6OW.js} +2 -2
- package/dist/config.js +1 -0
- package/dist/{create-agent-BI7UTJ6A.js → create-agent-7W57J7MT.js} +4 -3
- package/dist/{create-annotation-SNM2J6S4.js → create-annotation-W2XELBCQ.js} +4 -3
- package/dist/{create-api-key-23MXYC2L.js → create-api-key-MKRXKFJM.js} +4 -3
- package/dist/{create-dashboard-CPOOOIKK.js → create-dashboard-QGL7IODC.js} +4 -3
- package/dist/{create-dataset-BVXPVVY2.js → create-dataset-3PH7A4HG.js} +4 -3
- package/dist/{create-dataset-records-S7VFIIMR.js → create-dataset-records-4DZS3VRL.js} +4 -3
- package/dist/{create-evaluator-WJAAQOUE.js → create-evaluator-YWH6NC4M.js} +4 -3
- package/dist/create-mcp-server.js +3 -2
- package/dist/{create-project-BF7LMZH5.js → create-project-BOBQ32C5.js} +4 -3
- package/dist/{create-prompt-LZ3QHSU4.js → create-prompt-FLCFGITE.js} +3 -2
- package/dist/{create-prompt-tag-IF4J24QM.js → create-prompt-tag-EMPNIKEA.js} +3 -2
- package/dist/{create-scenario-BK4E5DEU.js → create-scenario-BSBIHUL6.js} +4 -3
- package/dist/{create-suite-HEQPNLND.js → create-suite-TWF6BBR4.js} +4 -3
- package/dist/{delete-agent-Y4T2G5PT.js → delete-agent-7MSYNY5E.js} +4 -3
- package/dist/{delete-annotation-KYDMQTZG.js → delete-annotation-ZT5IGN24.js} +4 -3
- package/dist/{delete-dashboard-3RW647WJ.js → delete-dashboard-BTIY5S3L.js} +4 -3
- package/dist/{delete-dataset-SZAHFHHS.js → delete-dataset-U45HQHPR.js} +4 -3
- package/dist/{delete-dataset-records-ISHKGEBH.js → delete-dataset-records-R43IMAWB.js} +4 -3
- package/dist/{delete-evaluator-VKIG5I3S.js → delete-evaluator-U6JMQ6C7.js} +4 -3
- package/dist/{delete-prompt-tag-VYYL4GTF.js → delete-prompt-tag-4EV4TDHB.js} +3 -2
- package/dist/{delete-workflow-SHNPYSWQ.js → delete-workflow-5QYALXEL.js} +4 -3
- package/dist/discover-evaluator-schema-MRGHVNTT.js +2175 -0
- package/dist/{discover-scenario-schema-MEEEVND7.js → discover-scenario-schema-UPBTCWPG.js} +3 -1
- package/dist/{discover-schema-3T52ORPB.js → discover-schema-ICGXPHUW.js} +3 -1
- package/dist/{get-agent-IZSP7AR5.js → get-agent-7QJVPH72.js} +4 -3
- package/dist/{get-analytics-EDFAYYIQ.js → get-analytics-PVERWOA5.js} +3 -2
- package/dist/{get-dashboard-WSAO6IQ4.js → get-dashboard-ZZPC3WMD.js} +4 -3
- package/dist/{get-dataset-BEVNXQNF.js → get-dataset-25TB2LQH.js} +4 -3
- package/dist/{get-evaluator-HCVXNPZR.js → get-evaluator-3FTRQKEC.js} +4 -3
- package/dist/{get-project-H4V3GYRQ.js → get-project-5OAXYC57.js} +4 -3
- package/dist/{get-prompt-EWRJVVGB.js → get-prompt-I753LZKZ.js} +3 -2
- package/dist/{get-scenario-24YUJS5W.js → get-scenario-DSSTR6FI.js} +4 -3
- package/dist/{get-simulation-run-UX2W6F6I.js → get-simulation-run-RQPMS2MC.js} +4 -3
- package/dist/{get-suite-B65ZKZJA.js → get-suite-GTOCY5PL.js} +4 -3
- package/dist/{get-trace-ZR7MIITH.js → get-trace-O5VT3NAC.js} +7 -9
- package/dist/{get-workflow-YROHUQJW.js → get-workflow-3EZDOEIF.js} +4 -3
- package/dist/http-server-2ACJ3CXW.js +24366 -0
- package/dist/index.js +20935 -1751
- package/dist/{langwatch-api-annotations-OPEXNTPF.js → langwatch-api-annotations-E65MI3WZ.js} +4 -3
- package/dist/{langwatch-api-dashboards-NPQM6QJI.js → langwatch-api-dashboards-QCDECRCY.js} +4 -3
- package/dist/{langwatch-api-monitors-3L25OOOS.js → langwatch-api-monitors-UIO2KTDV.js} +3 -2
- package/dist/{langwatch-api-secrets-ZFURUA62.js → langwatch-api-secrets-4T2EKSJ7.js} +3 -2
- package/dist/{langwatch-api-triggers-XGXXT7DD.js → langwatch-api-triggers-MPOEKPUY.js} +3 -2
- package/dist/{langwatch-api-workflows-CXCTTCXT.js → langwatch-api-workflows-5HRZ7HR4.js} +4 -3
- package/dist/{list-agents-6ZNOV7FK.js → list-agents-TIJTP566.js} +4 -3
- package/dist/{list-annotations-6P3IWILH.js → list-annotations-CGX5BT7E.js} +4 -3
- package/dist/{list-api-keys-JJI62KD2.js → list-api-keys-JLWJPFRX.js} +4 -3
- package/dist/{list-dashboards-G2WJOXWB.js → list-dashboards-RNIWX3TX.js} +4 -3
- package/dist/{list-dataset-records-GWWVOCII.js → list-dataset-records-B5MHZR66.js} +4 -3
- package/dist/{list-datasets-HBTH33X4.js → list-datasets-BVCAMQCP.js} +4 -3
- package/dist/{list-evaluators-K5OGB6TX.js → list-evaluators-65FBTL2U.js} +4 -3
- package/dist/{list-model-providers-JMOGZLSO.js → list-model-providers-GRK3I3VV.js} +4 -3
- package/dist/{list-projects-OXJC2NW5.js → list-projects-JLMBFMW3.js} +4 -3
- package/dist/{list-prompt-tags-J2HPHVAZ.js → list-prompt-tags-UHNWDGQI.js} +3 -2
- package/dist/{list-prompts-C7GR72XL.js → list-prompts-7254B3U7.js} +3 -2
- package/dist/{list-scenarios-JEPGIIDO.js → list-scenarios-46YNICKM.js} +4 -3
- package/dist/{list-simulation-runs-DRSAGPEC.js → list-simulation-runs-LGNEFNPN.js} +4 -3
- package/dist/{list-suites-POTZ3ZT6.js → list-suites-5VK4HXEK.js} +4 -3
- package/dist/{list-workflows-QQZQIOHB.js → list-workflows-MLQDM6CP.js} +4 -3
- package/dist/{rename-prompt-tag-4AAV2BS4.js → rename-prompt-tag-RHQMNEQL.js} +3 -2
- package/dist/report-issue-DXJ6TPTC.js +412 -0
- package/dist/{revoke-api-key-TONB4ADQ.js → revoke-api-key-3Y35EMBT.js} +4 -3
- package/dist/{run-agent-7QE3YEH7.js → run-agent-RBSIFKRT.js} +4 -3
- package/dist/{run-suite-Q66OSPO4.js → run-suite-K3DNQ3SE.js} +4 -3
- package/dist/{run-workflow-RWX2D752.js → run-workflow-5LVBZYLS.js} +4 -3
- package/dist/{search-traces-M5E5VB4X.js → search-traces-U4HLOCZ2.js} +9 -2
- package/dist/{set-model-provider-XENT5D2P.js → set-model-provider-V3M5CDIY.js} +4 -3
- package/dist/{update-agent-GML25EE3.js → update-agent-47RZIHS7.js} +4 -3
- package/dist/{update-dataset-R4MM6NNY.js → update-dataset-G6QJJGS5.js} +4 -3
- package/dist/{update-dataset-record-FN4BL5P4.js → update-dataset-record-RMWLSWCS.js} +4 -3
- package/dist/{update-evaluator-LH2RDDB5.js → update-evaluator-SFRRI5Q3.js} +4 -3
- package/dist/{update-project-H53IHRBB.js → update-project-PI5DWBVK.js} +4 -3
- package/dist/{update-prompt-M33OTTAJ.js → update-prompt-RQFTEO7Y.js} +3 -2
- package/dist/{update-scenario-FKTQRAFQ.js → update-scenario-G3IU2UIB.js} +4 -3
- package/dist/{update-suite-JJTNOTXN.js → update-suite-TRGGLNR7.js} +4 -3
- package/package.json +20 -18
- package/pnpm-workspace.yaml +20 -3
- package/pyproject.toml +9 -1
- package/src/__tests__/all-tools.integration.test.ts +56 -120
- package/src/__tests__/documentation-fetch-security.integration.test.ts +176 -0
- package/src/__tests__/langwatch-api.unit.test.ts +206 -0
- package/src/__tests__/public-http-request-security.integration.test.ts +118 -0
- package/src/__tests__/report-issue.integration.test.ts +147 -0
- package/src/__tests__/tools.unit.test.ts +24 -0
- package/src/create-mcp-server.ts +43 -29
- package/src/documentation-fetch.ts +111 -0
- package/src/langwatch-api-agents.ts +2 -2
- package/src/langwatch-api.ts +138 -8
- package/src/public-http-request.ts +242 -0
- package/src/tools/get-trace.ts +2 -12
- package/src/tools/report-issue.ts +150 -0
- package/src/tools/search-traces.ts +4 -0
- package/src/utils/format-evaluations.ts +20 -0
- package/tsconfig.json +8 -1
- package/uv.lock +259 -205
- package/dist/chunk-IUP5IHBD.js +0 -71
- package/dist/discover-evaluator-schema-H23XCLNE.js +0 -1402
- package/dist/http-server-GXVEDA7G.js +0 -226
|
@@ -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
|