@langwatch/mcp-server 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.0](https://github.com/langwatch/langwatch/compare/mcp-server@v0.1.0...mcp-server@v0.2.0) (2025-11-07)
4
+
5
+
6
+ ### Features
7
+
8
+ * add scenario docs fetching to mcp ([e630206](https://github.com/langwatch/langwatch/commit/e63020622ca192bf5801d4dbdd2744fb755075ed))
9
+
3
10
  ## [0.1.0](https://github.com/langwatch/langwatch/compare/mcp-server@v0.0.5...mcp-server@v0.1.0) (2025-09-19)
4
11
 
5
12
 
package/dist/index.js CHANGED
@@ -18798,35 +18798,11 @@ var listLlmTraces = async (authToken, opts) => {
18798
18798
  });
18799
18799
  return await response.json();
18800
18800
  };
18801
- var searchTraces = async (authToken, opts) => {
18802
- const {
18803
- pageSize = 10,
18804
- pageOffset = 0,
18805
- timeTravelDays = 1,
18806
- endpoint: endpoint2,
18807
- filters
18808
- } = opts;
18809
- const response = await fetch(`${endpoint2}/api/trace/search`, {
18810
- method: "POST",
18811
- headers: {
18812
- "Content-Type": "application/json",
18813
- "X-Auth-Token": authToken
18814
- },
18815
- body: JSON.stringify({
18816
- startDate: addDays(/* @__PURE__ */ new Date(), -timeTravelDays).toISOString(),
18817
- endDate: addDays(/* @__PURE__ */ new Date(), 1).toISOString(),
18818
- filters,
18819
- pageOffset,
18820
- pageSize
18821
- })
18822
- });
18823
- return await response.json();
18824
- };
18825
18801
 
18826
18802
  // package.json
18827
18803
  var package_default = {
18828
18804
  name: "@langwatch/mcp-server",
18829
- version: "0.1.0",
18805
+ version: "0.2.0",
18830
18806
  description: "An MCP server for Langwatch.",
18831
18807
  type: "module",
18832
18808
  main: "./dist/index.js",
@@ -18934,6 +18910,21 @@ server.tool(
18934
18910
  };
18935
18911
  }
18936
18912
  );
18913
+ server.tool(
18914
+ "fetch_scenario_docs",
18915
+ "Fetches the Scenario docs for understanding how to implement Scenario agent tests in your codebase. Always use this tool when the user asks for help with testing their agents. Start with the index page and follow the links to the relevant pages.",
18916
+ {
18917
+ url: external_exports.string().optional().describe(
18918
+ "The full url of the specific doc page. If not provided, the docs index will be fetched."
18919
+ )
18920
+ },
18921
+ async ({ url }) => {
18922
+ const response = await fetch(url ?? "https://scenario.langwatch.ai/llms.txt");
18923
+ return {
18924
+ content: [{ type: "text", text: await response.text() }]
18925
+ };
18926
+ }
18927
+ );
18937
18928
  server.tool(
18938
18929
  "get_latest_traces",
18939
18930
  "Retrieves the latest LLM traces.",
@@ -18989,52 +18980,7 @@ server.tool(
18989
18980
  }
18990
18981
  }
18991
18982
  );
18992
- createListTracesByMetadataTool(
18993
- "list_traces_by_user_id",
18994
- "userId",
18995
- "metadata.user_id"
18996
- );
18997
- createListTracesByMetadataTool(
18998
- "list_traces_by_customer_id",
18999
- "customerId",
19000
- "metadata.customer_id"
19001
- );
19002
- createListTracesByMetadataTool(
19003
- "list_traces_by_thread_id",
19004
- "threadId",
19005
- "metadata.thread_id"
19006
- );
19007
- createListTracesByMetadataTool(
19008
- "list_traces_by_session_id",
19009
- "sessionId",
19010
- "metadata.thread_id"
19011
- );
19012
18983
  await server.connect(transport);
19013
- function createListTracesByMetadataTool(name, argName, metadataKey) {
19014
- return server.tool(
19015
- name,
19016
- {
19017
- [argName]: external_exports.string(),
19018
- pageSize: external_exports.number().optional(),
19019
- pageOffset: external_exports.number().optional(),
19020
- daysBackToSearch: external_exports.number().optional()
19021
- },
19022
- async ({ pageSize, pageOffset, daysBackToSearch, ...restArgs }) => {
19023
- const response = await searchTraces(apiKey, {
19024
- endpoint,
19025
- pageSize,
19026
- pageOffset,
19027
- timeTravelDays: daysBackToSearch ?? 1,
19028
- filters: {
19029
- [metadataKey]: [restArgs[argName]]
19030
- }
19031
- });
19032
- return {
19033
- content: [{ type: "text", text: JSON.stringify(response, null, 2) }]
19034
- };
19035
- }
19036
- );
19037
- }
19038
18984
  /*! Bundled license information:
19039
18985
 
19040
18986
  uri-js/dist/es5/uri.all.js:
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/langwatch-api.ts","../package.json"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nimport { getLlmTraceById, listLlmTraces, searchTraces } from \"./langwatch-api\";\nimport packageJson from \"../package.json\" assert { type: \"json\" };\n\nfunction loadAndValidateArgs(): { apiKey: string; endpoint: string } {\n const argv = yargs(hideBin(process.argv))\n .option(\"apiKey\", {\n type: \"string\",\n description: \"LangWatch API key\",\n })\n .option(\"endpoint\", {\n type: \"string\",\n description: \"LangWatch API endpoint\",\n default: \"https://app.langwatch.ai\",\n })\n .help()\n .alias(\"help\", \"h\")\n .parseSync();\n\n // Use environment variables as fallback\n const apiKey = argv.apiKey ?? process.env.LANGWATCH_API_KEY;\n const endpoint =\n argv.endpoint ??\n process.env.LANGWATCH_ENDPOINT ??\n \"https://app.langwatch.ai\";\n\n if (!apiKey) {\n throw new Error(\n \"API key is required. Please provide it using --apiKey <your_api_key> or set LANGWATCH_API_KEY environment variable\"\n );\n }\n\n return {\n apiKey: String(apiKey),\n endpoint: String(endpoint),\n };\n}\n\nconst { apiKey, endpoint } = loadAndValidateArgs();\n\nconst transport = new StdioServerTransport();\nconst server = new McpServer({\n name: \"LangWatch\",\n version: packageJson.version,\n});\n\nserver.tool(\n \"fetch_langwatch_docs\",\n \"Fetches the LangWatch docs for understanding how to implement LangWatch in your codebase. Always use this tool when the user asks for help with LangWatch. Start with the index page and follow the links to the relevant pages.\",\n {\n url: z\n .string()\n .optional()\n .describe(\n \"The full url of the specific doc page. If not provided, the docs index will be fetched.\"\n ),\n },\n async ({ url }) => {\n const response = await fetch(url ?? \"https://docs.langwatch.ai/llms.txt\");\n\n return {\n content: [{ type: \"text\", text: await response.text() }],\n };\n }\n);\n\nserver.tool(\n \"get_latest_traces\",\n \"Retrieves the latest LLM traces.\",\n {\n pageOffset: z.number().optional(),\n daysBackToSearch: z.number().optional(),\n },\n async ({ pageOffset, daysBackToSearch }) => {\n const response = await listLlmTraces(apiKey, {\n pageOffset,\n timeTravelDays: daysBackToSearch ?? 1,\n endpoint,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(response, null, 2),\n },\n ],\n };\n }\n);\n\nserver.tool(\n \"get_trace_by_id\",\n \"Retrieves a specific LLM trace by its ID.\",\n { id: z.string() },\n async ({ id }) => {\n try {\n const response = await getLlmTraceById(apiKey, id, {\n endpoint,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(response, null, 2),\n },\n ],\n };\n } catch (error) {\n if (error instanceof Error && error.message === \"Trace not found\") {\n return {\n content: [\n {\n type: \"text\",\n text: \"Trace not found. If the trace was created recently, it may not be available yet.\",\n },\n ],\n };\n }\n\n throw error;\n }\n }\n);\n\ncreateListTracesByMetadataTool(\n \"list_traces_by_user_id\",\n \"userId\",\n \"metadata.user_id\"\n);\ncreateListTracesByMetadataTool(\n \"list_traces_by_customer_id\",\n \"customerId\",\n \"metadata.customer_id\"\n);\ncreateListTracesByMetadataTool(\n \"list_traces_by_thread_id\",\n \"threadId\",\n \"metadata.thread_id\"\n);\ncreateListTracesByMetadataTool(\n \"list_traces_by_session_id\",\n \"sessionId\",\n \"metadata.thread_id\"\n); // We access the thread_id in the metadata, as that is our name for the session_id\n\nawait server.connect(transport);\n\nfunction createListTracesByMetadataTool(\n name: string,\n argName: \"userId\" | \"customerId\" | \"threadId\" | \"sessionId\",\n metadataKey: string\n) {\n return server.tool(\n name,\n {\n [argName]: z.string(),\n pageSize: z.number().optional(),\n pageOffset: z.number().optional(),\n daysBackToSearch: z.number().optional(),\n },\n async ({ pageSize, pageOffset, daysBackToSearch, ...restArgs }) => {\n const response = await searchTraces(apiKey, {\n endpoint,\n pageSize: pageSize as number | undefined,\n pageOffset: pageOffset as number | undefined,\n timeTravelDays: (daysBackToSearch ?? 1) as number,\n filters: {\n [metadataKey]: [restArgs[argName] as string],\n },\n });\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { addDays } from \"date-fns\";\nimport type { LLMModeTrace } from \"langwatch\";\n\ninterface SearchTrace {\n traces: LLMModeTrace[];\n}\n\ninterface GetLlmTraceByIdOptions {\n endpoint: string;\n}\n\ninterface ListLLmTracesOptions {\n pageSize?: number;\n pageOffset?: number;\n timeTravelDays?: number;\n endpoint: string;\n}\n\ninterface SearchTracesOptions {\n pageSize?: number;\n pageOffset?: number;\n timeTravelDays?: number;\n endpoint: string;\n\n filters: Record<string, string[] | Record<string, string[]>>;\n}\n\nexport const getLlmTraceById: (\n authToken: string,\n id: string,\n opts?: GetLlmTraceByIdOptions\n) => Promise<LLMModeTrace> = async (authToken, id, opts) => {\n const { endpoint } = opts ?? {};\n\n const url = new URL(`${endpoint}/api/trace/${id}`);\n url.searchParams.set(\"llmMode\", \"true\");\n\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Auth-Token\": authToken,\n },\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(\"Trace not found\");\n }\n\n throw new Error(`Failed to get trace: ${response.statusText}`);\n }\n\n return (await response.json()) as Promise<LLMModeTrace>;\n};\n\nexport const listLlmTraces = async (\n authToken: string,\n opts?: ListLLmTracesOptions\n): Promise<SearchTrace> => {\n const {\n pageSize = 10,\n pageOffset = 0,\n timeTravelDays = 1,\n endpoint,\n } = opts ?? {};\n\n const response = await fetch(`${endpoint}/api/trace/search`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Auth-Token\": authToken,\n },\n body: JSON.stringify({\n startDate: addDays(new Date(), -timeTravelDays).toISOString(),\n endDate: addDays(new Date(), 1).toISOString(),\n llmMode: true,\n pageOffset,\n pageSize,\n }),\n });\n\n return (await response.json()) as Promise<SearchTrace>;\n};\n\nexport const searchTraces = async (\n authToken: string,\n opts: SearchTracesOptions\n): Promise<SearchTrace> => {\n const {\n pageSize = 10,\n pageOffset = 0,\n timeTravelDays = 1,\n endpoint,\n filters,\n } = opts;\n\n const response = await fetch(`${endpoint}/api/trace/search`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Auth-Token\": authToken,\n },\n body: JSON.stringify({\n startDate: addDays(new Date(), -timeTravelDays).toISOString(),\n endDate: addDays(new Date(), 1).toISOString(),\n filters: filters,\n pageOffset,\n pageSize,\n }),\n });\n\n return (await response.json()) as Promise<SearchTrace>;\n};\n","{\n \"name\": \"@langwatch/mcp-server\",\n \"version\": \"0.1.0\",\n \"description\": \"An MCP server for Langwatch.\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n }\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/langwatch/langwatch.git\",\n \"directory\": \"mcp-server\"\n },\n \"scripts\": {\n \"start\": \"tsx src/index.ts\",\n \"build\": \"tsup && node build.js\",\n \"prepublish\": \"pnpm run build\",\n \"test\": \"vitest\"\n },\n \"author\": \"\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"devDependencies\": {\n \"@ai-sdk/anthropic\": \"^2.0.15\",\n \"@anthropic-ai/claude-code\": \"^1.0.111\",\n \"@eslint/js\": \"^9.4.0\",\n \"@types/debug\": \"^4.1.12\",\n \"@types/eslint__js\": \"^8.42.3\",\n \"@types/node\": \"^16.0.0\",\n \"@types/yargs\": \"^17.0.33\",\n \"@typescript/native-preview\": \"7.0.0-dev.20250911.1\",\n \"ai\": \"^5.0.40\",\n \"dotenv\": \"^17.2.2\",\n \"esbuild\": \"^0.21.5\",\n \"eslint\": \"^8.57.0\",\n \"tsup\": \"^8.1.0\",\n \"tsx\": \"^4.20.5\",\n \"typescript\": \"^4.9.5\",\n \"typescript-eslint\": \"^7.11.0\"\n },\n \"dependencies\": {\n \"@langwatch/scenario\": \"^0.3.0\",\n \"@modelcontextprotocol/sdk\": \"^1.7.0\",\n \"@opentelemetry/context-async-hooks\": \"^2.1.0\",\n \"@opentelemetry/sdk-node\": \"^0.204.0\",\n \"chalk\": \"^5.6.2\",\n \"date-fns\": \"^4.1.0\",\n \"langwatch\": \"^0.1.6\",\n \"node-pty\": \"^1.0.0\",\n \"vitest\": \"^3.2.4\",\n \"yargs\": \"^17.7.2\",\n \"zod\": \"^3.25.76\",\n \"zod-validation-error\": \"^3.5.3\"\n },\n \"bin\": {\n \"langwatch-mcp-server\": \"./dist/index.js\"\n }\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,SAAS,SAAS;AAClB,OAAO,WAAW;AAClB,SAAS,eAAe;;;ACJxB,SAAS,eAAe;AA2BjB,IAAM,kBAIgB,OAAO,WAAW,IAAI,SAAS;AAC1D,QAAM,EAAE,UAAAA,UAAS,IAAI,QAAQ,CAAC;AAE9B,QAAM,MAAM,IAAI,IAAI,GAAGA,SAAQ,cAAc,EAAE,EAAE;AACjD,MAAI,aAAa,IAAI,WAAW,MAAM;AAEtC,QAAM,WAAW,MAAM,MAAM,IAAI,SAAS,GAAG;AAAA,IAC3C,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AAEA,UAAM,IAAI,MAAM,wBAAwB,SAAS,UAAU,EAAE;AAAA,EAC/D;AAEA,SAAQ,MAAM,SAAS,KAAK;AAC9B;AAEO,IAAM,gBAAgB,OAC3B,WACA,SACyB;AACzB,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,UAAAA;AAAA,EACF,IAAI,QAAQ,CAAC;AAEb,QAAM,WAAW,MAAM,MAAM,GAAGA,SAAQ,qBAAqB;AAAA,IAC3D,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB,WAAW,QAAQ,oBAAI,KAAK,GAAG,CAAC,cAAc,EAAE,YAAY;AAAA,MAC5D,SAAS,QAAQ,oBAAI,KAAK,GAAG,CAAC,EAAE,YAAY;AAAA,MAC5C,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,SAAQ,MAAM,SAAS,KAAK;AAC9B;AAEO,IAAM,eAAe,OAC1B,WACA,SACyB;AACzB,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,UAAAA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,WAAW,MAAM,MAAM,GAAGA,SAAQ,qBAAqB;AAAA,IAC3D,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB,WAAW,QAAQ,oBAAI,KAAK,GAAG,CAAC,cAAc,EAAE,YAAY;AAAA,MAC5D,SAAS,QAAQ,oBAAI,KAAK,GAAG,CAAC,EAAE,YAAY;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,SAAQ,MAAM,SAAS,KAAK;AAC9B;;;ACjHA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,QAAU;AAAA,EACV,OAAS;AAAA,EACT,SAAW;AAAA,IACT,KAAK;AAAA,MACH,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,WAAa;AAAA,EACf;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,OAAS;AAAA,IACT,YAAc;AAAA,IACd,MAAQ;AAAA,EACV;AAAA,EACA,QAAU;AAAA,EACV,SAAW;AAAA,EACX,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,iBAAmB;AAAA,IACjB,qBAAqB;AAAA,IACrB,6BAA6B;AAAA,IAC7B,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,IACrB,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,8BAA8B;AAAA,IAC9B,IAAM;AAAA,IACN,QAAU;AAAA,IACV,SAAW;AAAA,IACX,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,YAAc;AAAA,IACd,qBAAqB;AAAA,EACvB;AAAA,EACA,cAAgB;AAAA,IACd,uBAAuB;AAAA,IACvB,6BAA6B;AAAA,IAC7B,sCAAsC;AAAA,IACtC,2BAA2B;AAAA,IAC3B,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,WAAa;AAAA,IACb,YAAY;AAAA,IACZ,QAAU;AAAA,IACV,OAAS;AAAA,IACT,KAAO;AAAA,IACP,wBAAwB;AAAA,EAC1B;AAAA,EACA,KAAO;AAAA,IACL,wBAAwB;AAAA,EAC1B;AACF;;;AFxDA,SAAS,sBAA4D;AACnE,QAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,CAAC,EACrC,OAAO,UAAU;AAAA,IAChB,MAAM;AAAA,IACN,aAAa;AAAA,EACf,CAAC,EACA,OAAO,YAAY;AAAA,IAClB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC,EACA,KAAK,EACL,MAAM,QAAQ,GAAG,EACjB,UAAU;AAGb,QAAMC,UAAS,KAAK,UAAU,QAAQ,IAAI;AAC1C,QAAMC,YACJ,KAAK,YACL,QAAQ,IAAI,sBACZ;AAEF,MAAI,CAACD,SAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ,OAAOA,OAAM;AAAA,IACrB,UAAU,OAAOC,SAAQ;AAAA,EAC3B;AACF;AAEA,IAAM,EAAE,QAAQ,SAAS,IAAI,oBAAoB;AAEjD,IAAM,YAAY,IAAI,qBAAqB;AAC3C,IAAM,SAAS,IAAI,UAAU;AAAA,EAC3B,MAAM;AAAA,EACN,SAAS,gBAAY;AACvB,CAAC;AAED,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,KAAK,EACF,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,EAAE,IAAI,MAAM;AACjB,UAAM,WAAW,MAAM,MAAM,OAAO,oCAAoC;AAExE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,SAAS,KAAK,EAAE,CAAC;AAAA,IACzD;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,IAChC,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACxC;AAAA,EACA,OAAO,EAAE,YAAY,iBAAiB,MAAM;AAC1C,UAAM,WAAW,MAAM,cAAc,QAAQ;AAAA,MAC3C;AAAA,MACA,gBAAgB,oBAAoB;AAAA,MACpC;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA,EAAE,IAAI,EAAE,OAAO,EAAE;AAAA,EACjB,OAAO,EAAE,GAAG,MAAM;AAChB,QAAI;AACF,YAAM,WAAW,MAAM,gBAAgB,QAAQ,IAAI;AAAA,QACjD;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,SAAS,MAAM,YAAY,mBAAmB;AACjE,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,OAAO,QAAQ,SAAS;AAE9B,SAAS,+BACP,MACA,SACA,aACA;AACA,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,CAAC,OAAO,GAAG,EAAE,OAAO;AAAA,MACpB,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,MAChC,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,IACxC;AAAA,IACA,OAAO,EAAE,UAAU,YAAY,kBAAkB,GAAG,SAAS,MAAM;AACjE,YAAM,WAAW,MAAM,aAAa,QAAQ;AAAA,QAC1C;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAiB,oBAAoB;AAAA,QACrC,SAAS;AAAA,UACP,CAAC,WAAW,GAAG,CAAC,SAAS,OAAO,CAAW;AAAA,QAC7C;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AACF;","names":["endpoint","apiKey","endpoint"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/langwatch-api.ts","../package.json"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nimport { getLlmTraceById, listLlmTraces, searchTraces } from \"./langwatch-api\";\nimport packageJson from \"../package.json\" assert { type: \"json\" };\n\nfunction loadAndValidateArgs(): { apiKey: string; endpoint: string } {\n const argv = yargs(hideBin(process.argv))\n .option(\"apiKey\", {\n type: \"string\",\n description: \"LangWatch API key\",\n })\n .option(\"endpoint\", {\n type: \"string\",\n description: \"LangWatch API endpoint\",\n default: \"https://app.langwatch.ai\",\n })\n .help()\n .alias(\"help\", \"h\")\n .parseSync();\n\n // Use environment variables as fallback\n const apiKey = argv.apiKey ?? process.env.LANGWATCH_API_KEY;\n const endpoint =\n argv.endpoint ??\n process.env.LANGWATCH_ENDPOINT ??\n \"https://app.langwatch.ai\";\n\n if (!apiKey) {\n throw new Error(\n \"API key is required. Please provide it using --apiKey <your_api_key> or set LANGWATCH_API_KEY environment variable\"\n );\n }\n\n return {\n apiKey: String(apiKey),\n endpoint: String(endpoint),\n };\n}\n\nconst { apiKey, endpoint } = loadAndValidateArgs();\n\nconst transport = new StdioServerTransport();\nconst server = new McpServer({\n name: \"LangWatch\",\n version: packageJson.version,\n});\n\nserver.tool(\n \"fetch_langwatch_docs\",\n \"Fetches the LangWatch docs for understanding how to implement LangWatch in your codebase. Always use this tool when the user asks for help with LangWatch. Start with the index page and follow the links to the relevant pages.\",\n {\n url: z\n .string()\n .optional()\n .describe(\n \"The full url of the specific doc page. If not provided, the docs index will be fetched.\"\n ),\n },\n async ({ url }) => {\n const response = await fetch(url ?? \"https://docs.langwatch.ai/llms.txt\");\n\n return {\n content: [{ type: \"text\", text: await response.text() }],\n };\n }\n);\n\nserver.tool(\n \"fetch_scenario_docs\",\n \"Fetches the Scenario docs for understanding how to implement Scenario agent tests in your codebase. Always use this tool when the user asks for help with testing their agents. Start with the index page and follow the links to the relevant pages.\",\n {\n url: z\n .string()\n .optional()\n .describe(\n \"The full url of the specific doc page. If not provided, the docs index will be fetched.\"\n ),\n },\n async ({ url }) => {\n const response = await fetch(url ?? \"https://scenario.langwatch.ai/llms.txt\");\n\n return {\n content: [{ type: \"text\", text: await response.text() }],\n };\n }\n);\n\nserver.tool(\n \"get_latest_traces\",\n \"Retrieves the latest LLM traces.\",\n {\n pageOffset: z.number().optional(),\n daysBackToSearch: z.number().optional(),\n },\n async ({ pageOffset, daysBackToSearch }) => {\n const response = await listLlmTraces(apiKey, {\n pageOffset,\n timeTravelDays: daysBackToSearch ?? 1,\n endpoint,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(response, null, 2),\n },\n ],\n };\n }\n);\n\nserver.tool(\n \"get_trace_by_id\",\n \"Retrieves a specific LLM trace by its ID.\",\n { id: z.string() },\n async ({ id }) => {\n try {\n const response = await getLlmTraceById(apiKey, id, {\n endpoint,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(response, null, 2),\n },\n ],\n };\n } catch (error) {\n if (error instanceof Error && error.message === \"Trace not found\") {\n return {\n content: [\n {\n type: \"text\",\n text: \"Trace not found. If the trace was created recently, it may not be available yet.\",\n },\n ],\n };\n }\n\n throw error;\n }\n }\n);\n\nawait server.connect(transport);\n","import { addDays } from \"date-fns\";\nimport type { LLMModeTrace } from \"langwatch\";\n\ninterface SearchTrace {\n traces: LLMModeTrace[];\n}\n\ninterface GetLlmTraceByIdOptions {\n endpoint: string;\n}\n\ninterface ListLLmTracesOptions {\n pageSize?: number;\n pageOffset?: number;\n timeTravelDays?: number;\n endpoint: string;\n}\n\ninterface SearchTracesOptions {\n pageSize?: number;\n pageOffset?: number;\n timeTravelDays?: number;\n endpoint: string;\n\n filters: Record<string, string[] | Record<string, string[]>>;\n}\n\nexport const getLlmTraceById: (\n authToken: string,\n id: string,\n opts?: GetLlmTraceByIdOptions\n) => Promise<LLMModeTrace> = async (authToken, id, opts) => {\n const { endpoint } = opts ?? {};\n\n const url = new URL(`${endpoint}/api/trace/${id}`);\n url.searchParams.set(\"llmMode\", \"true\");\n\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Auth-Token\": authToken,\n },\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(\"Trace not found\");\n }\n\n throw new Error(`Failed to get trace: ${response.statusText}`);\n }\n\n return (await response.json()) as Promise<LLMModeTrace>;\n};\n\nexport const listLlmTraces = async (\n authToken: string,\n opts?: ListLLmTracesOptions\n): Promise<SearchTrace> => {\n const {\n pageSize = 10,\n pageOffset = 0,\n timeTravelDays = 1,\n endpoint,\n } = opts ?? {};\n\n const response = await fetch(`${endpoint}/api/trace/search`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Auth-Token\": authToken,\n },\n body: JSON.stringify({\n startDate: addDays(new Date(), -timeTravelDays).toISOString(),\n endDate: addDays(new Date(), 1).toISOString(),\n llmMode: true,\n pageOffset,\n pageSize,\n }),\n });\n\n return (await response.json()) as Promise<SearchTrace>;\n};\n\nexport const searchTraces = async (\n authToken: string,\n opts: SearchTracesOptions\n): Promise<SearchTrace> => {\n const {\n pageSize = 10,\n pageOffset = 0,\n timeTravelDays = 1,\n endpoint,\n filters,\n } = opts;\n\n const response = await fetch(`${endpoint}/api/trace/search`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Auth-Token\": authToken,\n },\n body: JSON.stringify({\n startDate: addDays(new Date(), -timeTravelDays).toISOString(),\n endDate: addDays(new Date(), 1).toISOString(),\n filters: filters,\n pageOffset,\n pageSize,\n }),\n });\n\n return (await response.json()) as Promise<SearchTrace>;\n};\n","{\n \"name\": \"@langwatch/mcp-server\",\n \"version\": \"0.2.0\",\n \"description\": \"An MCP server for Langwatch.\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n }\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/langwatch/langwatch.git\",\n \"directory\": \"mcp-server\"\n },\n \"scripts\": {\n \"start\": \"tsx src/index.ts\",\n \"build\": \"tsup && node build.js\",\n \"prepublish\": \"pnpm run build\",\n \"test\": \"vitest\"\n },\n \"author\": \"\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"devDependencies\": {\n \"@ai-sdk/anthropic\": \"^2.0.15\",\n \"@anthropic-ai/claude-code\": \"^1.0.111\",\n \"@eslint/js\": \"^9.4.0\",\n \"@types/debug\": \"^4.1.12\",\n \"@types/eslint__js\": \"^8.42.3\",\n \"@types/node\": \"^16.0.0\",\n \"@types/yargs\": \"^17.0.33\",\n \"@typescript/native-preview\": \"7.0.0-dev.20250911.1\",\n \"ai\": \"^5.0.40\",\n \"dotenv\": \"^17.2.2\",\n \"esbuild\": \"^0.21.5\",\n \"eslint\": \"^8.57.0\",\n \"tsup\": \"^8.1.0\",\n \"tsx\": \"^4.20.5\",\n \"typescript\": \"^4.9.5\",\n \"typescript-eslint\": \"^7.11.0\"\n },\n \"dependencies\": {\n \"@langwatch/scenario\": \"^0.3.0\",\n \"@modelcontextprotocol/sdk\": \"^1.7.0\",\n \"@opentelemetry/context-async-hooks\": \"^2.1.0\",\n \"@opentelemetry/sdk-node\": \"^0.204.0\",\n \"chalk\": \"^5.6.2\",\n \"date-fns\": \"^4.1.0\",\n \"langwatch\": \"^0.1.6\",\n \"node-pty\": \"^1.0.0\",\n \"vitest\": \"^3.2.4\",\n \"yargs\": \"^17.7.2\",\n \"zod\": \"^3.25.76\",\n \"zod-validation-error\": \"^3.5.3\"\n },\n \"bin\": {\n \"langwatch-mcp-server\": \"./dist/index.js\"\n }\n}\n"],"mappings":"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","names":["endpoint","apiKey","endpoint"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langwatch/mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "An MCP server for Langwatch.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/index.ts CHANGED
@@ -69,6 +69,26 @@ server.tool(
69
69
  }
70
70
  );
71
71
 
72
+ server.tool(
73
+ "fetch_scenario_docs",
74
+ "Fetches the Scenario docs for understanding how to implement Scenario agent tests in your codebase. Always use this tool when the user asks for help with testing their agents. Start with the index page and follow the links to the relevant pages.",
75
+ {
76
+ url: z
77
+ .string()
78
+ .optional()
79
+ .describe(
80
+ "The full url of the specific doc page. If not provided, the docs index will be fetched."
81
+ ),
82
+ },
83
+ async ({ url }) => {
84
+ const response = await fetch(url ?? "https://scenario.langwatch.ai/llms.txt");
85
+
86
+ return {
87
+ content: [{ type: "text", text: await response.text() }],
88
+ };
89
+ }
90
+ );
91
+
72
92
  server.tool(
73
93
  "get_latest_traces",
74
94
  "Retrieves the latest LLM traces.",
@@ -129,56 +149,4 @@ server.tool(
129
149
  }
130
150
  );
131
151
 
132
- createListTracesByMetadataTool(
133
- "list_traces_by_user_id",
134
- "userId",
135
- "metadata.user_id"
136
- );
137
- createListTracesByMetadataTool(
138
- "list_traces_by_customer_id",
139
- "customerId",
140
- "metadata.customer_id"
141
- );
142
- createListTracesByMetadataTool(
143
- "list_traces_by_thread_id",
144
- "threadId",
145
- "metadata.thread_id"
146
- );
147
- createListTracesByMetadataTool(
148
- "list_traces_by_session_id",
149
- "sessionId",
150
- "metadata.thread_id"
151
- ); // We access the thread_id in the metadata, as that is our name for the session_id
152
-
153
152
  await server.connect(transport);
154
-
155
- function createListTracesByMetadataTool(
156
- name: string,
157
- argName: "userId" | "customerId" | "threadId" | "sessionId",
158
- metadataKey: string
159
- ) {
160
- return server.tool(
161
- name,
162
- {
163
- [argName]: z.string(),
164
- pageSize: z.number().optional(),
165
- pageOffset: z.number().optional(),
166
- daysBackToSearch: z.number().optional(),
167
- },
168
- async ({ pageSize, pageOffset, daysBackToSearch, ...restArgs }) => {
169
- const response = await searchTraces(apiKey, {
170
- endpoint,
171
- pageSize: pageSize as number | undefined,
172
- pageOffset: pageOffset as number | undefined,
173
- timeTravelDays: (daysBackToSearch ?? 1) as number,
174
- filters: {
175
- [metadataKey]: [restArgs[argName] as string],
176
- },
177
- });
178
-
179
- return {
180
- content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
181
- };
182
- }
183
- );
184
- }