@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
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectSensitiveEnvValues,
|
|
3
|
+
REDACTION_AUDIT_URL,
|
|
4
|
+
redactReportText,
|
|
5
|
+
redactSessionJsonl,
|
|
6
|
+
truncateJsonlToByteBudget,
|
|
7
|
+
} from "@langwatch/redaction";
|
|
8
|
+
import { getConfig } from "../config.js";
|
|
9
|
+
|
|
10
|
+
/** Transcripts are capped after redaction; oldest lines are dropped first. */
|
|
11
|
+
const MAX_SESSION_BYTES = 8 * 1024 * 1024;
|
|
12
|
+
const REQUEST_TIMEOUT_MS = 60_000;
|
|
13
|
+
|
|
14
|
+
export interface ReportIssueParams {
|
|
15
|
+
user_approved: boolean;
|
|
16
|
+
title: string;
|
|
17
|
+
summary?: string;
|
|
18
|
+
session_content?: string;
|
|
19
|
+
contact_email?: string;
|
|
20
|
+
agent?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface RedactedReport {
|
|
24
|
+
title: string;
|
|
25
|
+
summary?: string;
|
|
26
|
+
sessionData?: string;
|
|
27
|
+
sessionTruncated: boolean;
|
|
28
|
+
redactedCount: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Redaction runs locally, before anything leaves the machine. */
|
|
32
|
+
function redactReport(params: ReportIssueParams): RedactedReport {
|
|
33
|
+
const envValues = collectSensitiveEnvValues(process.env);
|
|
34
|
+
let redactedCount = 0;
|
|
35
|
+
|
|
36
|
+
const titleResult = redactReportText({ text: params.title, envValues });
|
|
37
|
+
redactedCount += titleResult.redactedCount;
|
|
38
|
+
|
|
39
|
+
let summary: string | undefined;
|
|
40
|
+
if (params.summary) {
|
|
41
|
+
const result = redactReportText({ text: params.summary, envValues });
|
|
42
|
+
summary = result.text;
|
|
43
|
+
redactedCount += result.redactedCount;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let sessionData: string | undefined;
|
|
47
|
+
let sessionTruncated = false;
|
|
48
|
+
if (params.session_content) {
|
|
49
|
+
const redacted = redactSessionJsonl({
|
|
50
|
+
jsonl: params.session_content,
|
|
51
|
+
envValues,
|
|
52
|
+
});
|
|
53
|
+
redactedCount += redacted.redactedCount;
|
|
54
|
+
const truncated = truncateJsonlToByteBudget({
|
|
55
|
+
jsonl: redacted.text,
|
|
56
|
+
maxBytes: MAX_SESSION_BYTES,
|
|
57
|
+
});
|
|
58
|
+
sessionData = truncated.text;
|
|
59
|
+
sessionTruncated = truncated.truncated;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
title: titleResult.text,
|
|
64
|
+
summary,
|
|
65
|
+
sessionData,
|
|
66
|
+
sessionTruncated,
|
|
67
|
+
redactedCount,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function deliverReport(
|
|
72
|
+
report: RedactedReport,
|
|
73
|
+
params: ReportIssueParams,
|
|
74
|
+
): Promise<string> {
|
|
75
|
+
const config = getConfig();
|
|
76
|
+
const endpoint = config.endpoint.replace(/\/+$/, "");
|
|
77
|
+
|
|
78
|
+
const response = await fetch(`${endpoint}/api/bug-reports`, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers: {
|
|
81
|
+
"content-type": "application/json",
|
|
82
|
+
...(config.apiKey ? { authorization: `Bearer ${config.apiKey}` } : {}),
|
|
83
|
+
},
|
|
84
|
+
body: JSON.stringify({
|
|
85
|
+
source: "mcp",
|
|
86
|
+
kind: report.sessionData ? "full_session" : "summary",
|
|
87
|
+
title: report.title,
|
|
88
|
+
...(report.summary ? { summary: report.summary } : {}),
|
|
89
|
+
...(report.sessionData
|
|
90
|
+
? { sessionData: report.sessionData, sessionTruncated: report.sessionTruncated }
|
|
91
|
+
: {}),
|
|
92
|
+
...(params.agent ? { agent: params.agent } : {}),
|
|
93
|
+
...(params.contact_email ? { contactEmail: params.contact_email } : {}),
|
|
94
|
+
}),
|
|
95
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
96
|
+
}).catch(() => {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Could not reach ${endpoint} to deliver the report. Retry in a moment; if it ` +
|
|
99
|
+
"keeps failing, email support@langwatch.ai with the same content.",
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const body = (await response.text().catch(() => "")).slice(0, 300);
|
|
105
|
+
throw new Error(
|
|
106
|
+
`The reports endpoint answered HTTP ${response.status}: ${body}. Retry in a ` +
|
|
107
|
+
"moment; if it keeps failing, email support@langwatch.ai.",
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const { id } = (await response.json()) as { id: string };
|
|
112
|
+
return id;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Sends an issue report to the LangWatch team. Deliberately does NOT require
|
|
117
|
+
* an API key: the reporter may be struggling precisely because setup failed.
|
|
118
|
+
* When a key is configured it only links the report to the project.
|
|
119
|
+
*/
|
|
120
|
+
export async function handleReportIssue(
|
|
121
|
+
params: ReportIssueParams,
|
|
122
|
+
): Promise<string> {
|
|
123
|
+
if (!params.user_approved) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"This sends a report to the LangWatch team, so the user must approve it first. " +
|
|
126
|
+
'Ask the user: "Can I send this issue report to LangWatch to help them fix it?" ' +
|
|
127
|
+
"If they agree, call again with user_approved=true. Secrets and personal data " +
|
|
128
|
+
`are redacted locally before sending; audit the rules at ${REDACTION_AUDIT_URL}`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!params.summary?.trim() && !params.session_content?.trim()) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
"Nothing to report: pass a summary (what you tried, verbatim errors, what " +
|
|
135
|
+
"you had to figure out), session_content, or both.",
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const report = redactReport(params);
|
|
140
|
+
const id = await deliverReport(report, params);
|
|
141
|
+
|
|
142
|
+
return [
|
|
143
|
+
`Report sent to the LangWatch team (${id}). Thank you!`,
|
|
144
|
+
`Redacted ${report.redactedCount} sensitive value${report.redactedCount === 1 ? "" : "s"} locally before sending.`,
|
|
145
|
+
...(report.sessionTruncated
|
|
146
|
+
? ["The session content was truncated to the most recent activity to fit the upload limit."]
|
|
147
|
+
: []),
|
|
148
|
+
"Reports like this directly shape what gets fixed next.",
|
|
149
|
+
].join(" ");
|
|
150
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { searchTraces as apiSearchTraces } from "../langwatch-api.js";
|
|
2
2
|
import { parseRelativeDate } from "../utils/date-parsing.js";
|
|
3
|
+
import { formatEvaluationLines } from "../utils/format-evaluations.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Handles the search_traces MCP tool invocation.
|
|
@@ -74,6 +75,9 @@ export async function handleSearchTraces(params: {
|
|
|
74
75
|
if (trace.error) {
|
|
75
76
|
lines.push(`- **Error**: ${JSON.stringify(trace.error)}`);
|
|
76
77
|
}
|
|
78
|
+
if (trace.evaluations && trace.evaluations.length > 0) {
|
|
79
|
+
lines.push(...formatEvaluationLines(trace.evaluations));
|
|
80
|
+
}
|
|
77
81
|
lines.push("");
|
|
78
82
|
}
|
|
79
83
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface EvaluationSummary {
|
|
2
|
+
evaluator_id?: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
score?: number;
|
|
5
|
+
passed?: boolean;
|
|
6
|
+
label?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Formats a trace's evaluation results as markdown bullet lines, one per evaluation. */
|
|
10
|
+
export function formatEvaluationLines(evaluations: EvaluationSummary[]): string[] {
|
|
11
|
+
return evaluations.map((evaluation) => {
|
|
12
|
+
const status =
|
|
13
|
+
evaluation.passed === true
|
|
14
|
+
? "PASSED"
|
|
15
|
+
: evaluation.passed === false
|
|
16
|
+
? "FAILED"
|
|
17
|
+
: "N/A";
|
|
18
|
+
return `- **${evaluation.name || evaluation.evaluator_id}**: ${status}${evaluation.score != null ? ` (score: ${evaluation.score})` : ""}${evaluation.label ? ` [${evaluation.label}]` : ""}`;
|
|
19
|
+
});
|
|
20
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -12,7 +12,14 @@
|
|
|
12
12
|
"checkJs": true,
|
|
13
13
|
"skipLibCheck": true,
|
|
14
14
|
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
"moduleResolution": "
|
|
15
|
+
"moduleResolution": "bundler",
|
|
16
|
+
"rootDir": "..",
|
|
17
|
+
// The evaluator catalog we import (langevals/ts-integration/evaluators.generated.ts)
|
|
18
|
+
// is Zod-first and imports `zod`, but lives outside this package's
|
|
19
|
+
// node_modules tree, so plain resolution cannot find it. Point `zod` at this
|
|
20
|
+
// package's own copy (a declared dependency) so the type-checker resolves it.
|
|
21
|
+
// Paths are resolved relative to this tsconfig (no baseUrl — tsgo removed it).
|
|
22
|
+
"paths": { "zod": ["./node_modules/zod"] },
|
|
16
23
|
"isolatedModules": true,
|
|
17
24
|
"jsx": "preserve",
|
|
18
25
|
"incremental": true,
|