@langwatch/mcp-server 0.2.1 → 0.2.2
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 +7 -0
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.2](https://github.com/langwatch/langwatch/compare/mcp-server@v0.2.1...mcp-server@v0.2.2) (2025-11-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* fix fetching llms txt for first request ([#813](https://github.com/langwatch/langwatch/issues/813)) ([cd8de19](https://github.com/langwatch/langwatch/commit/cd8de19b2a06556cd3b89b6cc868db7aac563efc))
|
|
9
|
+
|
|
3
10
|
## [0.2.1](https://github.com/langwatch/langwatch/compare/mcp-server@v0.2.0...mcp-server@v0.2.1) (2025-11-08)
|
|
4
11
|
|
|
5
12
|
|
package/dist/index.js
CHANGED
|
@@ -18802,7 +18802,7 @@ var listLlmTraces = async (authToken, opts) => {
|
|
|
18802
18802
|
// package.json
|
|
18803
18803
|
var package_default = {
|
|
18804
18804
|
name: "@langwatch/mcp-server",
|
|
18805
|
-
version: "0.2.
|
|
18805
|
+
version: "0.2.2",
|
|
18806
18806
|
description: "An MCP server for Langwatch.",
|
|
18807
18807
|
type: "module",
|
|
18808
18808
|
main: "./dist/index.js",
|
|
@@ -18897,7 +18897,7 @@ var server = new McpServer({
|
|
|
18897
18897
|
});
|
|
18898
18898
|
server.tool(
|
|
18899
18899
|
"fetch_langwatch_docs",
|
|
18900
|
-
"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
|
|
18900
|
+
"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 empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension",
|
|
18901
18901
|
{
|
|
18902
18902
|
url: external_exports.string().optional().describe(
|
|
18903
18903
|
"The full url of the specific doc page. If not provided, the docs index will be fetched."
|
|
@@ -18905,7 +18905,7 @@ server.tool(
|
|
|
18905
18905
|
},
|
|
18906
18906
|
async ({ url }) => {
|
|
18907
18907
|
let urlToFetch = url ?? "https://docs.langwatch.ai/llms.txt";
|
|
18908
|
-
if (url && !urlToFetch.endsWith(".md")) {
|
|
18908
|
+
if (url && !urlToFetch.endsWith(".md") && !urlToFetch.endsWith(".txt")) {
|
|
18909
18909
|
urlToFetch += ".md";
|
|
18910
18910
|
}
|
|
18911
18911
|
const response = await fetch(urlToFetch);
|
|
@@ -18916,7 +18916,7 @@ server.tool(
|
|
|
18916
18916
|
);
|
|
18917
18917
|
server.tool(
|
|
18918
18918
|
"fetch_scenario_docs",
|
|
18919
|
-
"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
|
|
18919
|
+
"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 empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension",
|
|
18920
18920
|
{
|
|
18921
18921
|
url: external_exports.string().optional().describe(
|
|
18922
18922
|
"The full url of the specific doc page. If not provided, the docs index will be fetched."
|
|
@@ -18924,7 +18924,7 @@ server.tool(
|
|
|
18924
18924
|
},
|
|
18925
18925
|
async ({ url }) => {
|
|
18926
18926
|
let urlToFetch = url ?? "https://scenario.langwatch.ai/llms.txt";
|
|
18927
|
-
if (url && !urlToFetch.endsWith(".md")) {
|
|
18927
|
+
if (url && !urlToFetch.endsWith(".md") && !urlToFetch.endsWith(".txt")) {
|
|
18928
18928
|
urlToFetch += ".md";
|
|
18929
18929
|
}
|
|
18930
18930
|
const response = await fetch(urlToFetch);
|
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, always ending with `.md` extension\",\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 let urlToFetch = url ?? \"https://docs.langwatch.ai/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\")) {\n urlToFetch += \".md\";\n }\n const response = await fetch(urlToFetch);\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, always ending with `.md` extension\",\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 let urlToFetch = url ?? \"https://scenario.langwatch.ai/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\")) {\n urlToFetch += \".md\";\n }\n const response = await fetch(urlToFetch);\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.1\",\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"]}
|
|
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 empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension\",\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 let urlToFetch = url ?? \"https://docs.langwatch.ai/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\") && !urlToFetch.endsWith(\".txt\")) {\n urlToFetch += \".md\";\n }\n const response = await fetch(urlToFetch);\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 empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension\",\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 let urlToFetch = url ?? \"https://scenario.langwatch.ai/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\") && !urlToFetch.endsWith(\".txt\")) {\n urlToFetch += \".md\";\n }\n const response = await fetch(urlToFetch);\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.2\",\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
package/src/index.ts
CHANGED
|
@@ -51,7 +51,7 @@ const server = new McpServer({
|
|
|
51
51
|
|
|
52
52
|
server.tool(
|
|
53
53
|
"fetch_langwatch_docs",
|
|
54
|
-
"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
|
|
54
|
+
"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 empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension",
|
|
55
55
|
{
|
|
56
56
|
url: z
|
|
57
57
|
.string()
|
|
@@ -62,7 +62,7 @@ server.tool(
|
|
|
62
62
|
},
|
|
63
63
|
async ({ url }) => {
|
|
64
64
|
let urlToFetch = url ?? "https://docs.langwatch.ai/llms.txt";
|
|
65
|
-
if (url && !urlToFetch.endsWith(".md")) {
|
|
65
|
+
if (url && !urlToFetch.endsWith(".md") && !urlToFetch.endsWith(".txt")) {
|
|
66
66
|
urlToFetch += ".md";
|
|
67
67
|
}
|
|
68
68
|
const response = await fetch(urlToFetch);
|
|
@@ -75,7 +75,7 @@ server.tool(
|
|
|
75
75
|
|
|
76
76
|
server.tool(
|
|
77
77
|
"fetch_scenario_docs",
|
|
78
|
-
"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
|
|
78
|
+
"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 empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension",
|
|
79
79
|
{
|
|
80
80
|
url: z
|
|
81
81
|
.string()
|
|
@@ -86,7 +86,7 @@ server.tool(
|
|
|
86
86
|
},
|
|
87
87
|
async ({ url }) => {
|
|
88
88
|
let urlToFetch = url ?? "https://scenario.langwatch.ai/llms.txt";
|
|
89
|
-
if (url && !urlToFetch.endsWith(".md")) {
|
|
89
|
+
if (url && !urlToFetch.endsWith(".md") && !urlToFetch.endsWith(".txt")) {
|
|
90
90
|
urlToFetch += ".md";
|
|
91
91
|
}
|
|
92
92
|
const response = await fetch(urlToFetch);
|