@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.
- package/.release-please-shim +1 -1
- package/CHANGELOG.md +62 -0
- package/README.md +9 -17
- package/dist/{archive-project-HZBRPR2S.js → archive-project-MK3673A7.js} +4 -3
- package/dist/{archive-scenario-P5RRITRM.js → archive-scenario-KATSXRIN.js} +4 -3
- package/dist/{archive-suite-NUUFD2EM.js → archive-suite-C3KX6IIZ.js} +4 -3
- package/dist/{assign-prompt-tag-FKCCZPML.js → assign-prompt-tag-E3C5W6PI.js} +3 -2
- package/dist/chunk-37SMPMQS.js +12 -0
- package/dist/{chunk-42ZHHHIJ.js → chunk-5UWY24RP.js} +79 -4
- package/dist/chunk-BJ7B4R26.js +42 -0
- package/dist/chunk-CE6QMZOP.js +432 -0
- package/dist/{chunk-X2SEURT2.js → chunk-DAIQKS27.js} +2 -2
- package/dist/{chunk-R7C7OUVG.js → chunk-EU22L52K.js} +2 -2
- package/dist/{chunk-TROIWSEQ.js → chunk-J45SVWPR.js} +2 -2
- package/dist/{chunk-CCM4ZFGF.js → chunk-O3LWVN67.js} +2 -2
- package/dist/{chunk-BB7EOKHR.js → chunk-RYRB2YVJ.js} +2 -2
- package/dist/{chunk-HKY3GW45.js → chunk-T7WJVS2N.js} +2 -2
- package/dist/{chunk-JHOSVOHT.js → chunk-UXXA4D6K.js} +2 -2
- package/dist/{chunk-FVDAZ4XG.js → chunk-VYPSKRPN.js} +219 -137
- package/dist/{chunk-CHKCEZBP.js → chunk-WDH5P5RF.js} +2 -2
- package/dist/{chunk-BBJ5WAJB.js → chunk-WWMDHZZV.js} +2 -2
- package/dist/{chunk-ADSJ2FDA.js → chunk-XY4STOBE.js} +2 -2
- package/dist/{chunk-BYWYM2RP.js → chunk-Y3HDZ6OW.js} +2 -2
- package/dist/config.js +1 -0
- package/dist/{create-agent-K5Q7BFGZ.js → create-agent-7W57J7MT.js} +4 -3
- package/dist/{create-annotation-KN3GE3DK.js → create-annotation-W2XELBCQ.js} +4 -3
- package/dist/{create-api-key-OQI5PUNQ.js → create-api-key-MKRXKFJM.js} +4 -3
- package/dist/{create-dashboard-G4QA5AXP.js → create-dashboard-QGL7IODC.js} +4 -3
- package/dist/{create-dataset-WQSC37N7.js → create-dataset-3PH7A4HG.js} +4 -3
- package/dist/{create-dataset-records-B4RL3FLC.js → create-dataset-records-4DZS3VRL.js} +4 -3
- package/dist/{create-evaluator-YFFQIR7E.js → create-evaluator-YWH6NC4M.js} +4 -3
- package/dist/create-mcp-server.js +3 -2
- package/dist/{create-project-CUVQ67VN.js → create-project-BOBQ32C5.js} +4 -3
- package/dist/{create-prompt-NGXKSP4X.js → create-prompt-FLCFGITE.js} +3 -2
- package/dist/{create-prompt-tag-IUKYPVHH.js → create-prompt-tag-EMPNIKEA.js} +3 -2
- package/dist/{create-scenario-FNBXALH3.js → create-scenario-BSBIHUL6.js} +4 -3
- package/dist/{create-suite-DJEPD4ZB.js → create-suite-TWF6BBR4.js} +4 -3
- package/dist/{delete-agent-TJI5XBBM.js → delete-agent-7MSYNY5E.js} +4 -3
- package/dist/{delete-annotation-KRP53TUU.js → delete-annotation-ZT5IGN24.js} +4 -3
- package/dist/{delete-dashboard-N5SZJIR3.js → delete-dashboard-BTIY5S3L.js} +4 -3
- package/dist/{delete-dataset-KDUOHL2P.js → delete-dataset-U45HQHPR.js} +4 -3
- package/dist/{delete-dataset-records-DM4W3PAW.js → delete-dataset-records-R43IMAWB.js} +4 -3
- package/dist/{delete-evaluator-7ZATLJOA.js → delete-evaluator-U6JMQ6C7.js} +4 -3
- package/dist/{delete-prompt-tag-I6HNMSVJ.js → delete-prompt-tag-4EV4TDHB.js} +3 -2
- package/dist/{delete-workflow-QEO74JQR.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-3KDWCP5N.js → get-agent-7QJVPH72.js} +4 -3
- package/dist/{get-analytics-GPVJX7SF.js → get-analytics-PVERWOA5.js} +3 -2
- package/dist/{get-dashboard-YPTIE5YY.js → get-dashboard-ZZPC3WMD.js} +4 -3
- package/dist/{get-dataset-6DQFYITM.js → get-dataset-25TB2LQH.js} +4 -3
- package/dist/{get-evaluator-PCM6XQAU.js → get-evaluator-3FTRQKEC.js} +4 -3
- package/dist/{get-project-JCMWXVLU.js → get-project-5OAXYC57.js} +4 -3
- package/dist/{get-prompt-5XAGWWBG.js → get-prompt-I753LZKZ.js} +3 -2
- package/dist/{get-scenario-7XBCDZWX.js → get-scenario-DSSTR6FI.js} +4 -3
- package/dist/{get-simulation-run-AV24FJWI.js → get-simulation-run-RQPMS2MC.js} +4 -3
- package/dist/{get-suite-4DBVHFEM.js → get-suite-GTOCY5PL.js} +4 -3
- package/dist/{get-trace-MRBDS3HJ.js → get-trace-O5VT3NAC.js} +7 -9
- package/dist/{get-workflow-UR4Y6UFX.js → get-workflow-3EZDOEIF.js} +4 -3
- package/dist/http-server-2ACJ3CXW.js +24366 -0
- package/dist/index.js +23374 -3140
- package/dist/{langwatch-api-annotations-ZJDRB4JH.js → langwatch-api-annotations-E65MI3WZ.js} +4 -3
- package/dist/{langwatch-api-dashboards-WARLI6NF.js → langwatch-api-dashboards-QCDECRCY.js} +4 -3
- package/dist/{langwatch-api-monitors-4XKXHYCG.js → langwatch-api-monitors-UIO2KTDV.js} +3 -2
- package/dist/{langwatch-api-secrets-6SHK5G7Q.js → langwatch-api-secrets-4T2EKSJ7.js} +3 -2
- package/dist/{langwatch-api-triggers-5SX6R2WU.js → langwatch-api-triggers-MPOEKPUY.js} +3 -2
- package/dist/{langwatch-api-workflows-NLJENNXE.js → langwatch-api-workflows-5HRZ7HR4.js} +4 -3
- package/dist/{list-agents-NECO7MPI.js → list-agents-TIJTP566.js} +4 -3
- package/dist/{list-annotations-3OJEO774.js → list-annotations-CGX5BT7E.js} +4 -3
- package/dist/{list-api-keys-AWW7ROLB.js → list-api-keys-JLWJPFRX.js} +4 -3
- package/dist/{list-dashboards-DVPVVVKW.js → list-dashboards-RNIWX3TX.js} +4 -3
- package/dist/{list-dataset-records-I4BYORF5.js → list-dataset-records-B5MHZR66.js} +4 -3
- package/dist/{list-datasets-WUAE5HGX.js → list-datasets-BVCAMQCP.js} +4 -3
- package/dist/{list-evaluators-B6OSVAM2.js → list-evaluators-65FBTL2U.js} +4 -3
- package/dist/{list-model-providers-NL6IP4UZ.js → list-model-providers-GRK3I3VV.js} +4 -3
- package/dist/{list-projects-5FHMJ4PQ.js → list-projects-JLMBFMW3.js} +4 -3
- package/dist/{list-prompt-tags-Z2DD6FLQ.js → list-prompt-tags-UHNWDGQI.js} +3 -2
- package/dist/{list-prompts-VNXKHK7T.js → list-prompts-7254B3U7.js} +3 -2
- package/dist/{list-scenarios-CFZHXL76.js → list-scenarios-46YNICKM.js} +4 -3
- package/dist/{list-simulation-runs-AM2BXLBW.js → list-simulation-runs-LGNEFNPN.js} +4 -3
- package/dist/{list-suites-ZDOHAAXF.js → list-suites-5VK4HXEK.js} +4 -3
- package/dist/{list-workflows-WBRBKLIT.js → list-workflows-MLQDM6CP.js} +4 -3
- package/dist/{rename-prompt-tag-A4RJUK7Z.js → rename-prompt-tag-RHQMNEQL.js} +3 -2
- package/dist/report-issue-DXJ6TPTC.js +412 -0
- package/dist/{revoke-api-key-ZSPSPF5G.js → revoke-api-key-3Y35EMBT.js} +4 -3
- package/dist/{run-agent-JFNDY7MR.js → run-agent-RBSIFKRT.js} +4 -3
- package/dist/{run-suite-TH7LO5TJ.js → run-suite-K3DNQ3SE.js} +4 -3
- package/dist/{run-workflow-CK3JP5U2.js → run-workflow-5LVBZYLS.js} +4 -3
- package/dist/{search-traces-3BBVYPC3.js → search-traces-U4HLOCZ2.js} +9 -2
- package/dist/{set-model-provider-WOC5FNMV.js → set-model-provider-V3M5CDIY.js} +4 -3
- package/dist/{update-agent-YMEV5MTL.js → update-agent-47RZIHS7.js} +4 -3
- package/dist/{update-dataset-EYT5POFM.js → update-dataset-G6QJJGS5.js} +4 -3
- package/dist/{update-dataset-record-VFF5JTX4.js → update-dataset-record-RMWLSWCS.js} +4 -3
- package/dist/{update-evaluator-6IJHFG2E.js → update-evaluator-SFRRI5Q3.js} +4 -3
- package/dist/{update-project-OIT4WPFI.js → update-project-PI5DWBVK.js} +4 -3
- package/dist/{update-prompt-ZU2DD6KM.js → update-prompt-RQFTEO7Y.js} +3 -2
- package/dist/{update-scenario-3VUTPDRU.js → update-scenario-G3IU2UIB.js} +4 -3
- package/dist/{update-suite-C6JFDQHL.js → update-suite-TRGGLNR7.js} +4 -3
- package/package.json +20 -18
- package/pnpm-workspace.yaml +27 -2
- 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-XC62KJIT.js +0 -71
- package/dist/discover-evaluator-schema-H23XCLNE.js +0 -1402
- 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
|