@langwatch/mcp-server 0.4.0 → 0.5.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/archive-scenario-GAE4XVFM.js +19 -0
  3. package/dist/archive-scenario-GAE4XVFM.js.map +1 -0
  4. package/dist/{chunk-HOPTUDCZ.js → chunk-JVWDWL3J.js} +3 -2
  5. package/dist/chunk-JVWDWL3J.js.map +1 -0
  6. package/dist/chunk-K2YFPOSD.js +40 -0
  7. package/dist/chunk-K2YFPOSD.js.map +1 -0
  8. package/dist/{create-prompt-UBC537BJ.js → create-prompt-P35POKBW.js} +2 -2
  9. package/dist/create-scenario-3YRZVDYF.js +26 -0
  10. package/dist/create-scenario-3YRZVDYF.js.map +1 -0
  11. package/dist/discover-scenario-schema-MEEEVND7.js +65 -0
  12. package/dist/discover-scenario-schema-MEEEVND7.js.map +1 -0
  13. package/dist/{get-analytics-3IFTN6MY.js → get-analytics-BAVXTAPB.js} +2 -2
  14. package/dist/{get-prompt-2ZB5B3QC.js → get-prompt-LKCPT26O.js} +2 -2
  15. package/dist/get-scenario-3SCDW4Z6.js +33 -0
  16. package/dist/get-scenario-3SCDW4Z6.js.map +1 -0
  17. package/dist/{get-trace-7IXKKCJJ.js → get-trace-QFDWJ5D4.js} +2 -2
  18. package/dist/index.js +16040 -8719
  19. package/dist/index.js.map +1 -1
  20. package/dist/{list-prompts-J72LTP7Z.js → list-prompts-UQPBCUYA.js} +2 -2
  21. package/dist/list-scenarios-573YOUKC.js +40 -0
  22. package/dist/list-scenarios-573YOUKC.js.map +1 -0
  23. package/dist/{search-traces-RW2NDHN5.js → search-traces-RSMYCAN7.js} +2 -2
  24. package/dist/{update-prompt-G6HHZSUM.js → update-prompt-G2Y5EBQY.js} +2 -2
  25. package/dist/update-scenario-SSGVOBJO.js +27 -0
  26. package/dist/update-scenario-SSGVOBJO.js.map +1 -0
  27. package/package.json +3 -3
  28. package/src/__tests__/scenario-tools.integration.test.ts +286 -0
  29. package/src/__tests__/scenario-tools.unit.test.ts +185 -0
  30. package/src/index.ts +132 -3
  31. package/src/langwatch-api-scenarios.ts +67 -0
  32. package/src/langwatch-api.ts +4 -3
  33. package/src/tools/archive-scenario.ts +19 -0
  34. package/src/tools/create-scenario.ts +30 -0
  35. package/src/tools/discover-scenario-schema.ts +71 -0
  36. package/src/tools/get-scenario.ts +36 -0
  37. package/src/tools/list-scenarios.ts +47 -0
  38. package/src/tools/update-scenario.ts +32 -0
  39. package/uv.lock +1788 -1322
  40. package/dist/chunk-HOPTUDCZ.js.map +0 -1
  41. /package/dist/{create-prompt-UBC537BJ.js.map → create-prompt-P35POKBW.js.map} +0 -0
  42. /package/dist/{get-analytics-3IFTN6MY.js.map → get-analytics-BAVXTAPB.js.map} +0 -0
  43. /package/dist/{get-prompt-2ZB5B3QC.js.map → get-prompt-LKCPT26O.js.map} +0 -0
  44. /package/dist/{get-trace-7IXKKCJJ.js.map → get-trace-QFDWJ5D4.js.map} +0 -0
  45. /package/dist/{list-prompts-J72LTP7Z.js.map → list-prompts-UQPBCUYA.js.map} +0 -0
  46. /package/dist/{search-traces-RW2NDHN5.js.map → search-traces-RSMYCAN7.js.map} +0 -0
  47. /package/dist/{update-prompt-G6HHZSUM.js.map → update-prompt-G2Y5EBQY.js.map} +0 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../package.json"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { z } from \"zod\";\n\nimport packageJson from \"../package.json\" assert { type: \"json\" };\nimport { initConfig } from \"./config.js\";\n\nconst argv = await 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 })\n .help()\n .parseAsync();\n\ninitConfig({\n apiKey: argv.apiKey,\n endpoint: argv.endpoint,\n});\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://langwatch.ai/docs/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\") && !urlToFetch.endsWith(\".txt\")) {\n urlToFetch += \".md\";\n }\n if (!urlToFetch.startsWith(\"http\")) {\n if (!urlToFetch.startsWith(\"/\")) {\n urlToFetch = \"/\" + urlToFetch;\n }\n urlToFetch = \"https://langwatch.ai/docs\" + urlToFetch;\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://langwatch.ai/scenario/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\") && !urlToFetch.endsWith(\".txt\")) {\n urlToFetch += \".md\";\n }\n if (!urlToFetch.startsWith(\"http\")) {\n if (!urlToFetch.startsWith(\"/\")) {\n urlToFetch = \"/\" + urlToFetch;\n }\n urlToFetch = \"https://langwatch.ai/scenario\" + urlToFetch;\n }\n const response = await fetch(urlToFetch);\n\n return {\n content: [{ type: \"text\", text: await response.text() }],\n };\n }\n);\n\n// --- Observability Tools (require API key) ---\n\nserver.tool(\n \"discover_schema\",\n \"Discover available filter fields, metrics, aggregation types, and group-by options for LangWatch queries. Call this before using search_traces or get_analytics to understand available options.\",\n {\n category: z\n .enum([\"filters\", \"metrics\", \"aggregations\", \"groups\", \"all\"])\n .describe(\"Which schema category to discover\"),\n },\n async ({ category }) => {\n const { formatSchema } = await import(\"./tools/discover-schema.js\");\n return { content: [{ type: \"text\", text: formatSchema(category) }] };\n }\n);\n\nserver.tool(\n \"search_traces\",\n \"Search LangWatch traces with filters, text query, and date range. Returns AI-readable trace digests by default. Use format: 'json' for full raw data.\",\n {\n query: z.string().optional().describe(\"Text search query\"),\n filters: z\n .record(z.string(), z.array(z.string()))\n .optional()\n .describe(\n 'Filter traces. Format: {\"field\": [\"value\"]}. Use discover_schema for field names.'\n ),\n startDate: z\n .string()\n .optional()\n .describe(\n 'Start date: ISO string or relative like \"24h\", \"7d\", \"30d\". Default: 24h ago'\n ),\n endDate: z\n .string()\n .optional()\n .describe(\"End date: ISO string or relative. Default: now\"),\n pageSize: z\n .number()\n .optional()\n .describe(\"Results per page (default: 25, max: 1000)\"),\n scrollId: z\n .string()\n .optional()\n .describe(\"Pagination token from previous search\"),\n format: z\n .enum([\"digest\", \"json\"])\n .optional()\n .describe(\n \"Output format: 'digest' (default, AI-readable) or 'json' (full raw data)\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleSearchTraces } = await import(\"./tools/search-traces.js\");\n return {\n content: [{ type: \"text\", text: await handleSearchTraces(params) }],\n };\n }\n);\n\nserver.tool(\n \"get_trace\",\n \"Get full details of a single trace by ID. Returns AI-readable trace digest by default. Use format: 'json' for full raw data including all spans.\",\n {\n traceId: z.string().describe(\"The trace ID to retrieve\"),\n format: z\n .enum([\"digest\", \"json\"])\n .optional()\n .describe(\n \"Output format: 'digest' (default, AI-readable) or 'json' (full raw data)\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleGetTrace } = await import(\"./tools/get-trace.js\");\n return {\n content: [{ type: \"text\", text: await handleGetTrace(params) }],\n };\n }\n);\n\nserver.tool(\n \"get_analytics\",\n 'Query analytics timeseries from LangWatch. Metrics use \"category.name\" format (e.g., \"performance.completion_time\"). Use discover_schema to see available metrics.',\n {\n metric: z\n .string()\n .describe(\n 'Metric in \"category.name\" format, e.g., \"metadata.trace_id\", \"performance.total_cost\"'\n ),\n aggregation: z\n .string()\n .optional()\n .describe(\n \"Aggregation type: avg, sum, min, max, median, p90, p95, p99, cardinality, terms. Default: avg\"\n ),\n startDate: z\n .string()\n .optional()\n .describe('Start date: ISO or relative (\"7d\", \"30d\"). Default: 7 days ago'),\n endDate: z.string().optional().describe(\"End date. Default: now\"),\n timeZone: z.string().optional().describe(\"Timezone. Default: UTC\"),\n groupBy: z\n .string()\n .optional()\n .describe(\n \"Group results by field. Use discover_schema for options.\"\n ),\n filters: z\n .record(z.string(), z.array(z.string()))\n .optional()\n .describe(\"Filters to apply\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleGetAnalytics } = await import(\"./tools/get-analytics.js\");\n return {\n content: [{ type: \"text\", text: await handleGetAnalytics(params) }],\n };\n }\n);\n\nserver.tool(\n \"list_prompts\",\n \"List all prompts configured in the LangWatch project.\",\n {},\n async () => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleListPrompts } = await import(\"./tools/list-prompts.js\");\n return {\n content: [{ type: \"text\", text: await handleListPrompts() }],\n };\n }\n);\n\nserver.tool(\n \"get_prompt\",\n \"Get a specific prompt by ID or handle, including messages, model config, and version history.\",\n {\n idOrHandle: z.string().describe(\"Prompt ID or handle\"),\n version: z\n .number()\n .optional()\n .describe(\"Specific version number (default: latest)\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleGetPrompt } = await import(\"./tools/get-prompt.js\");\n return {\n content: [{ type: \"text\", text: await handleGetPrompt(params) }],\n };\n }\n);\n\nserver.tool(\n \"create_prompt\",\n \"Create a new prompt in the LangWatch project.\",\n {\n name: z.string().describe(\"Prompt name\"),\n handle: z\n .string()\n .optional()\n .describe(\"URL-friendly handle (auto-generated if omitted)\"),\n messages: z\n .array(\n z.object({\n role: z\n .enum([\"system\", \"user\", \"assistant\"])\n .describe(\"Message role\"),\n content: z.string().describe(\"Message content\"),\n })\n )\n .describe(\"Prompt messages\"),\n model: z\n .string()\n .describe('Model name, e.g., \"gpt-4o\", \"claude-sonnet-4-5-20250929\"'),\n modelProvider: z\n .string()\n .describe('Provider name, e.g., \"openai\", \"anthropic\"'),\n description: z.string().optional().describe(\"Prompt description\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleCreatePrompt } = await import(\"./tools/create-prompt.js\");\n return {\n content: [{ type: \"text\", text: await handleCreatePrompt(params) }],\n };\n }\n);\n\nserver.tool(\n \"update_prompt\",\n \"Update an existing prompt or create a new version.\",\n {\n idOrHandle: z.string().describe(\"Prompt ID or handle to update\"),\n messages: z\n .array(\n z.object({\n role: z.enum([\"system\", \"user\", \"assistant\"]),\n content: z.string(),\n })\n )\n .optional()\n .describe(\"Updated messages\"),\n model: z.string().optional().describe(\"Updated model name\"),\n modelProvider: z.string().optional().describe(\"Updated provider\"),\n commitMessage: z\n .string()\n .optional()\n .describe(\"Commit message for the change\"),\n createVersion: z\n .boolean()\n .optional()\n .describe(\n \"If true, creates a new version instead of updating in place\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleUpdatePrompt } = await import(\"./tools/update-prompt.js\");\n return {\n content: [{ type: \"text\", text: await handleUpdatePrompt(params) }],\n };\n }\n);\n\nawait server.connect(transport);\n","{\n \"name\": \"@langwatch/mcp-server\",\n \"version\": \"0.4.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 \"@langwatch/scenario\": \"^0.3.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 \"@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 \"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,OAAO,WAAW;AAClB,SAAS,eAAe;AACxB,SAAS,SAAS;;;ACJlB;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,uBAAuB;AAAA,IACvB,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,6BAA6B;AAAA,IAC7B,sCAAsC;AAAA,IACtC,2BAA2B;AAAA,IAC3B,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,QAAU;AAAA,IACV,OAAS;AAAA,IACT,KAAO;AAAA,IACP,wBAAwB;AAAA,EAC1B;AAAA,EACA,KAAO;AAAA,IACL,wBAAwB;AAAA,EAC1B;AACF;;;ADvDA,IAAM,OAAO,MAAM,MAAM,QAAQ,QAAQ,IAAI,CAAC,EAC3C,OAAO,UAAU;AAAA,EAChB,MAAM;AAAA,EACN,aAAa;AACf,CAAC,EACA,OAAO,YAAY;AAAA,EAClB,MAAM;AAAA,EACN,aAAa;AACf,CAAC,EACA,KAAK,EACL,WAAW;AAEd,WAAW;AAAA,EACT,QAAQ,KAAK;AAAA,EACb,UAAU,KAAK;AACjB,CAAC;AAED,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,QAAI,aAAa,OAAO;AACxB,QAAI,OAAO,CAAC,WAAW,SAAS,KAAK,KAAK,CAAC,WAAW,SAAS,MAAM,GAAG;AACtE,oBAAc;AAAA,IAChB;AACA,QAAI,CAAC,WAAW,WAAW,MAAM,GAAG;AAClC,UAAI,CAAC,WAAW,WAAW,GAAG,GAAG;AAC/B,qBAAa,MAAM;AAAA,MACrB;AACA,mBAAa,8BAA8B;AAAA,IAC7C;AACA,UAAM,WAAW,MAAM,MAAM,UAAU;AAEvC,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,KAAK,EACF,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,EAAE,IAAI,MAAM;AACjB,QAAI,aAAa,OAAO;AACxB,QAAI,OAAO,CAAC,WAAW,SAAS,KAAK,KAAK,CAAC,WAAW,SAAS,MAAM,GAAG;AACtE,oBAAc;AAAA,IAChB;AACA,QAAI,CAAC,WAAW,WAAW,MAAM,GAAG;AAClC,UAAI,CAAC,WAAW,WAAW,GAAG,GAAG;AAC/B,qBAAa,MAAM;AAAA,MACrB;AACA,mBAAa,kCAAkC;AAAA,IACjD;AACA,UAAM,WAAW,MAAM,MAAM,UAAU;AAEvC,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,SAAS,KAAK,EAAE,CAAC;AAAA,IACzD;AAAA,EACF;AACF;AAIA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,UAAU,EACP,KAAK,CAAC,WAAW,WAAW,gBAAgB,UAAU,KAAK,CAAC,EAC5D,SAAS,mCAAmC;AAAA,EACjD;AAAA,EACA,OAAO,EAAE,SAAS,MAAM;AACtB,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,+BAA4B;AAClE,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,aAAa,QAAQ,EAAE,CAAC,EAAE;AAAA,EACrE;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mBAAmB;AAAA,IACzD,SAAS,EACN,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EACtC,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,WAAW,EACR,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,EACN,OAAO,EACP,SAAS,EACT,SAAS,gDAAgD;AAAA,IAC5D,UAAU,EACP,OAAO,EACP,SAAS,EACT,SAAS,2CAA2C;AAAA,IACvD,UAAU,EACP,OAAO,EACP,SAAS,EACT,SAAS,uCAAuC;AAAA,IACnD,QAAQ,EACL,KAAK,CAAC,UAAU,MAAM,CAAC,EACvB,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,WAAW;AAChB,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,kBAAc;AACd,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,6BAA0B;AACtE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,mBAAmB,MAAM,EAAE,CAAC;AAAA,IACpE;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,SAAS,EAAE,OAAO,EAAE,SAAS,0BAA0B;AAAA,IACvD,QAAQ,EACL,KAAK,CAAC,UAAU,MAAM,CAAC,EACvB,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,WAAW;AAChB,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,kBAAc;AACd,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,yBAAsB;AAC9D,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,eAAe,MAAM,EAAE,CAAC;AAAA,IAChE;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,QAAQ,EACL,OAAO,EACP;AAAA,MACC;AAAA,IACF;AAAA,IACF,aAAa,EACV,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,WAAW,EACR,OAAO,EACP,SAAS,EACT,SAAS,gEAAgE;AAAA,IAC5E,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wBAAwB;AAAA,IAChE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wBAAwB;AAAA,IACjE,SAAS,EACN,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,EACN,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EACtC,SAAS,EACT,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,OAAO,WAAW;AAChB,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,kBAAc;AACd,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,6BAA0B;AACtE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,mBAAmB,MAAM,EAAE,CAAC;AAAA,IACpE;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA,CAAC;AAAA,EACD,YAAY;AACV,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,kBAAc;AACd,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,4BAAyB;AACpE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,kBAAkB,EAAE,CAAC;AAAA,IAC7D;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,YAAY,EAAE,OAAO,EAAE,SAAS,qBAAqB;AAAA,IACrD,SAAS,EACN,OAAO,EACP,SAAS,EACT,SAAS,2CAA2C;AAAA,EACzD;AAAA,EACA,OAAO,WAAW;AAChB,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,kBAAc;AACd,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,0BAAuB;AAChE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,gBAAgB,MAAM,EAAE,CAAC;AAAA,IACjE;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa;AAAA,IACvC,QAAQ,EACL,OAAO,EACP,SAAS,EACT,SAAS,iDAAiD;AAAA,IAC7D,UAAU,EACP;AAAA,MACC,EAAE,OAAO;AAAA,QACP,MAAM,EACH,KAAK,CAAC,UAAU,QAAQ,WAAW,CAAC,EACpC,SAAS,cAAc;AAAA,QAC1B,SAAS,EAAE,OAAO,EAAE,SAAS,iBAAiB;AAAA,MAChD,CAAC;AAAA,IACH,EACC,SAAS,iBAAiB;AAAA,IAC7B,OAAO,EACJ,OAAO,EACP,SAAS,0DAA0D;AAAA,IACtE,eAAe,EACZ,OAAO,EACP,SAAS,4CAA4C;AAAA,IACxD,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oBAAoB;AAAA,EAClE;AAAA,EACA,OAAO,WAAW;AAChB,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,kBAAc;AACd,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,6BAA0B;AACtE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,mBAAmB,MAAM,EAAE,CAAC;AAAA,IACpE;AAAA,EACF;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,YAAY,EAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,IAC/D,UAAU,EACP;AAAA,MACC,EAAE,OAAO;AAAA,QACP,MAAM,EAAE,KAAK,CAAC,UAAU,QAAQ,WAAW,CAAC;AAAA,QAC5C,SAAS,EAAE,OAAO;AAAA,MACpB,CAAC;AAAA,IACH,EACC,SAAS,EACT,SAAS,kBAAkB;AAAA,IAC9B,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oBAAoB;AAAA,IAC1D,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kBAAkB;AAAA,IAChE,eAAe,EACZ,OAAO,EACP,SAAS,EACT,SAAS,+BAA+B;AAAA,IAC3C,eAAe,EACZ,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,WAAW;AAChB,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,kBAAc;AACd,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,6BAA0B;AACtE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,mBAAmB,MAAM,EAAE,CAAC;AAAA,IACpE;AAAA,EACF;AACF;AAEA,MAAM,OAAO,QAAQ,SAAS;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../package.json"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { z } from \"zod\";\n\nimport packageJson from \"../package.json\" assert { type: \"json\" };\nimport { initConfig } from \"./config.js\";\n\nconst argv = await 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 })\n .help()\n .parseAsync();\n\ninitConfig({\n apiKey: argv.apiKey,\n endpoint: argv.endpoint,\n});\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://langwatch.ai/docs/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\") && !urlToFetch.endsWith(\".txt\")) {\n urlToFetch += \".md\";\n }\n if (!urlToFetch.startsWith(\"http\")) {\n if (!urlToFetch.startsWith(\"/\")) {\n urlToFetch = \"/\" + urlToFetch;\n }\n urlToFetch = \"https://langwatch.ai/docs\" + urlToFetch;\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://langwatch.ai/scenario/llms.txt\";\n if (url && !urlToFetch.endsWith(\".md\") && !urlToFetch.endsWith(\".txt\")) {\n urlToFetch += \".md\";\n }\n if (!urlToFetch.startsWith(\"http\")) {\n if (!urlToFetch.startsWith(\"/\")) {\n urlToFetch = \"/\" + urlToFetch;\n }\n urlToFetch = \"https://langwatch.ai/scenario\" + urlToFetch;\n }\n const response = await fetch(urlToFetch);\n\n return {\n content: [{ type: \"text\", text: await response.text() }],\n };\n }\n);\n\n// --- Observability Tools (require API key) ---\n\nserver.tool(\n \"discover_schema\",\n \"Discover available filter fields, metrics, aggregation types, group-by options, and scenario schema for LangWatch queries. Call this before using search_traces, get_analytics, or scenario tools to understand available options.\",\n {\n category: z\n .enum([\"filters\", \"metrics\", \"aggregations\", \"groups\", \"scenarios\", \"all\"])\n .describe(\"Which schema category to discover\"),\n },\n async ({ category }) => {\n if (category === \"scenarios\") {\n const { formatScenarioSchema } = await import(\"./tools/discover-scenario-schema.js\");\n return { content: [{ type: \"text\", text: formatScenarioSchema() }] };\n }\n const { formatSchema } = await import(\"./tools/discover-schema.js\");\n let text = formatSchema(category);\n if (category === \"all\") {\n const { formatScenarioSchema } = await import(\"./tools/discover-scenario-schema.js\");\n text += \"\\n\\n\" + formatScenarioSchema();\n }\n return { content: [{ type: \"text\", text }] };\n }\n);\n\nserver.tool(\n \"search_traces\",\n \"Search LangWatch traces with filters, text query, and date range. Returns AI-readable trace digests by default. Use format: 'json' for full raw data.\",\n {\n query: z.string().optional().describe(\"Text search query\"),\n filters: z\n .record(z.string(), z.array(z.string()))\n .optional()\n .describe(\n 'Filter traces. Format: {\"field\": [\"value\"]}. Use discover_schema for field names.'\n ),\n startDate: z\n .string()\n .optional()\n .describe(\n 'Start date: ISO string or relative like \"24h\", \"7d\", \"30d\". Default: 24h ago'\n ),\n endDate: z\n .string()\n .optional()\n .describe(\"End date: ISO string or relative. Default: now\"),\n pageSize: z\n .number()\n .optional()\n .describe(\"Results per page (default: 25, max: 1000)\"),\n scrollId: z\n .string()\n .optional()\n .describe(\"Pagination token from previous search\"),\n format: z\n .enum([\"digest\", \"json\"])\n .optional()\n .describe(\n \"Output format: 'digest' (default, AI-readable) or 'json' (full raw data)\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleSearchTraces } = await import(\"./tools/search-traces.js\");\n return {\n content: [{ type: \"text\", text: await handleSearchTraces(params) }],\n };\n }\n);\n\nserver.tool(\n \"get_trace\",\n \"Get full details of a single trace by ID. Returns AI-readable trace digest by default. Use format: 'json' for full raw data including all spans.\",\n {\n traceId: z.string().describe(\"The trace ID to retrieve\"),\n format: z\n .enum([\"digest\", \"json\"])\n .optional()\n .describe(\n \"Output format: 'digest' (default, AI-readable) or 'json' (full raw data)\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleGetTrace } = await import(\"./tools/get-trace.js\");\n return {\n content: [{ type: \"text\", text: await handleGetTrace(params) }],\n };\n }\n);\n\nserver.tool(\n \"get_analytics\",\n 'Query analytics timeseries from LangWatch. Metrics use \"category.name\" format (e.g., \"performance.completion_time\"). Use discover_schema to see available metrics.',\n {\n metric: z\n .string()\n .describe(\n 'Metric in \"category.name\" format, e.g., \"metadata.trace_id\", \"performance.total_cost\"'\n ),\n aggregation: z\n .string()\n .optional()\n .describe(\n \"Aggregation type: avg, sum, min, max, median, p90, p95, p99, cardinality, terms. Default: avg\"\n ),\n startDate: z\n .string()\n .optional()\n .describe('Start date: ISO or relative (\"7d\", \"30d\"). Default: 7 days ago'),\n endDate: z.string().optional().describe(\"End date. Default: now\"),\n timeZone: z.string().optional().describe(\"Timezone. Default: UTC\"),\n groupBy: z\n .string()\n .optional()\n .describe(\n \"Group results by field. Use discover_schema for options.\"\n ),\n filters: z\n .record(z.string(), z.array(z.string()))\n .optional()\n .describe(\"Filters to apply\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleGetAnalytics } = await import(\"./tools/get-analytics.js\");\n return {\n content: [{ type: \"text\", text: await handleGetAnalytics(params) }],\n };\n }\n);\n\nserver.tool(\n \"list_prompts\",\n \"List all prompts configured in the LangWatch project.\",\n {},\n async () => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleListPrompts } = await import(\"./tools/list-prompts.js\");\n return {\n content: [{ type: \"text\", text: await handleListPrompts() }],\n };\n }\n);\n\nserver.tool(\n \"get_prompt\",\n \"Get a specific prompt by ID or handle, including messages, model config, and version history.\",\n {\n idOrHandle: z.string().describe(\"Prompt ID or handle\"),\n version: z\n .number()\n .optional()\n .describe(\"Specific version number (default: latest)\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleGetPrompt } = await import(\"./tools/get-prompt.js\");\n return {\n content: [{ type: \"text\", text: await handleGetPrompt(params) }],\n };\n }\n);\n\nserver.tool(\n \"create_prompt\",\n \"Create a new prompt in the LangWatch project.\",\n {\n name: z.string().describe(\"Prompt name\"),\n handle: z\n .string()\n .optional()\n .describe(\"URL-friendly handle (auto-generated if omitted)\"),\n messages: z\n .array(\n z.object({\n role: z\n .enum([\"system\", \"user\", \"assistant\"])\n .describe(\"Message role\"),\n content: z.string().describe(\"Message content\"),\n })\n )\n .describe(\"Prompt messages\"),\n model: z\n .string()\n .describe('Model name, e.g., \"gpt-4o\", \"claude-sonnet-4-5-20250929\"'),\n modelProvider: z\n .string()\n .describe('Provider name, e.g., \"openai\", \"anthropic\"'),\n description: z.string().optional().describe(\"Prompt description\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleCreatePrompt } = await import(\"./tools/create-prompt.js\");\n return {\n content: [{ type: \"text\", text: await handleCreatePrompt(params) }],\n };\n }\n);\n\nserver.tool(\n \"update_prompt\",\n \"Update an existing prompt or create a new version.\",\n {\n idOrHandle: z.string().describe(\"Prompt ID or handle to update\"),\n messages: z\n .array(\n z.object({\n role: z.enum([\"system\", \"user\", \"assistant\"]),\n content: z.string(),\n })\n )\n .optional()\n .describe(\"Updated messages\"),\n model: z.string().optional().describe(\"Updated model name\"),\n modelProvider: z.string().optional().describe(\"Updated provider\"),\n commitMessage: z\n .string()\n .optional()\n .describe(\"Commit message for the change\"),\n createVersion: z\n .boolean()\n .optional()\n .describe(\n \"If true, creates a new version instead of updating in place\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleUpdatePrompt } = await import(\"./tools/update-prompt.js\");\n return {\n content: [{ type: \"text\", text: await handleUpdatePrompt(params) }],\n };\n }\n);\n\n// --- Scenario Tools (require API key) ---\n\nserver.tool(\n \"list_scenarios\",\n \"List all scenarios in the LangWatch project. Returns AI-readable digest by default.\",\n {\n format: z\n .enum([\"digest\", \"json\"])\n .optional()\n .describe(\n \"Output format: 'digest' (default, AI-readable) or 'json' (full raw data)\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleListScenarios } = await import(\"./tools/list-scenarios.js\");\n return {\n content: [{ type: \"text\", text: await handleListScenarios(params) }],\n };\n }\n);\n\nserver.tool(\n \"get_scenario\",\n \"Get full details of a scenario by ID, including situation, criteria, and labels.\",\n {\n scenarioId: z.string().describe(\"The scenario ID to retrieve\"),\n format: z\n .enum([\"digest\", \"json\"])\n .optional()\n .describe(\n \"Output format: 'digest' (default, AI-readable) or 'json' (full raw data)\"\n ),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleGetScenario } = await import(\"./tools/get-scenario.js\");\n return {\n content: [{ type: \"text\", text: await handleGetScenario(params) }],\n };\n }\n);\n\nserver.tool(\n \"create_scenario\",\n \"Create a new scenario in the LangWatch project. Call discover_schema({ category: 'scenarios' }) first to learn how to write effective situations and criteria.\",\n {\n name: z.string().describe(\"Scenario name\"),\n situation: z\n .string()\n .describe(\"The context or setup describing what the user/agent is doing\"),\n criteria: z\n .array(z.string())\n .optional()\n .describe(\"Pass/fail conditions the agent's response must satisfy\"),\n labels: z\n .array(z.string())\n .optional()\n .describe(\"Tags for organizing and filtering scenarios\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleCreateScenario } = await import(\n \"./tools/create-scenario.js\"\n );\n return {\n content: [{ type: \"text\", text: await handleCreateScenario(params) }],\n };\n }\n);\n\nserver.tool(\n \"update_scenario\",\n \"Update an existing scenario.\",\n {\n scenarioId: z.string().describe(\"The scenario ID to update\"),\n name: z.string().optional().describe(\"Updated scenario name\"),\n situation: z.string().optional().describe(\"Updated situation\"),\n criteria: z\n .array(z.string())\n .optional()\n .describe(\"Updated criteria\"),\n labels: z\n .array(z.string())\n .optional()\n .describe(\"Updated labels\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleUpdateScenario } = await import(\n \"./tools/update-scenario.js\"\n );\n return {\n content: [{ type: \"text\", text: await handleUpdateScenario(params) }],\n };\n }\n);\n\nserver.tool(\n \"archive_scenario\",\n \"Archive (soft-delete) a scenario.\",\n {\n scenarioId: z.string().describe(\"The scenario ID to archive\"),\n },\n async (params) => {\n const { requireApiKey } = await import(\"./config.js\");\n requireApiKey();\n const { handleArchiveScenario } = await import(\n \"./tools/archive-scenario.js\"\n );\n return {\n content: [{ type: \"text\", text: await handleArchiveScenario(params) }],\n };\n }\n);\n\nawait server.connect(transport);\n","{\n \"name\": \"@langwatch/mcp-server\",\n \"version\": \"0.5.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\": \"^2.1.7\",\n \"@eslint/js\": \"^9.4.0\",\n \"@langwatch/scenario\": \"^0.3.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.25.0\",\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 \"@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 \"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":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  listPrompts
3
- } from "./chunk-HOPTUDCZ.js";
3
+ } from "./chunk-JVWDWL3J.js";
4
4
  import "./chunk-AAQNA53E.js";
5
5
 
6
6
  // src/tools/list-prompts.ts
@@ -30,4 +30,4 @@ async function handleListPrompts() {
30
30
  export {
31
31
  handleListPrompts
32
32
  };
33
- //# sourceMappingURL=list-prompts-J72LTP7Z.js.map
33
+ //# sourceMappingURL=list-prompts-UQPBCUYA.js.map
@@ -0,0 +1,40 @@
1
+ import {
2
+ listScenarios
3
+ } from "./chunk-K2YFPOSD.js";
4
+ import "./chunk-JVWDWL3J.js";
5
+ import "./chunk-AAQNA53E.js";
6
+
7
+ // src/tools/list-scenarios.ts
8
+ async function handleListScenarios(params) {
9
+ const scenarios = await listScenarios();
10
+ if (params.format === "json") {
11
+ return JSON.stringify(scenarios, null, 2);
12
+ }
13
+ if (!Array.isArray(scenarios) || scenarios.length === 0) {
14
+ return "No scenarios found in this project.\n\n> Tip: Use `create_scenario` to create your first scenario.";
15
+ }
16
+ const lines = [];
17
+ lines.push(`# Scenarios (${scenarios.length} total)
18
+ `);
19
+ for (const s of scenarios) {
20
+ lines.push(`## ${s.name}`);
21
+ lines.push(`**ID**: ${s.id}`);
22
+ const preview = s.situation && s.situation.length > 60 ? s.situation.slice(0, 60) + "..." : s.situation;
23
+ lines.push(`**Situation**: ${preview}`);
24
+ lines.push(
25
+ `**Criteria**: ${Array.isArray(s.criteria) ? s.criteria.length : 0} criteria`
26
+ );
27
+ if (Array.isArray(s.labels) && s.labels.length > 0) {
28
+ lines.push(`**Labels**: ${s.labels.join(", ")}`);
29
+ }
30
+ lines.push("");
31
+ }
32
+ lines.push(
33
+ "> Use `get_scenario` with the ID to see full scenario details."
34
+ );
35
+ return lines.join("\n");
36
+ }
37
+ export {
38
+ handleListScenarios
39
+ };
40
+ //# sourceMappingURL=list-scenarios-573YOUKC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/list-scenarios.ts"],"sourcesContent":["import { listScenarios as apiListScenarios } from \"../langwatch-api-scenarios.js\";\n\n/**\n * Handles the list_scenarios MCP tool invocation.\n *\n * Lists all scenarios in the LangWatch project, formatted as an\n * AI-readable digest or raw JSON.\n */\nexport async function handleListScenarios(params: {\n format?: \"digest\" | \"json\";\n}): Promise<string> {\n const scenarios = await apiListScenarios();\n\n if (params.format === \"json\") {\n return JSON.stringify(scenarios, null, 2);\n }\n\n if (!Array.isArray(scenarios) || scenarios.length === 0) {\n return \"No scenarios found in this project.\\n\\n> Tip: Use `create_scenario` to create your first scenario.\";\n }\n\n const lines: string[] = [];\n lines.push(`# Scenarios (${scenarios.length} total)\\n`);\n\n for (const s of scenarios) {\n lines.push(`## ${s.name}`);\n lines.push(`**ID**: ${s.id}`);\n const preview =\n s.situation && s.situation.length > 60\n ? s.situation.slice(0, 60) + \"...\"\n : s.situation;\n lines.push(`**Situation**: ${preview}`);\n lines.push(\n `**Criteria**: ${Array.isArray(s.criteria) ? s.criteria.length : 0} criteria`,\n );\n if (Array.isArray(s.labels) && s.labels.length > 0) {\n lines.push(`**Labels**: ${s.labels.join(\", \")}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\n \"> Use `get_scenario` with the ID to see full scenario details.\",\n );\n\n return lines.join(\"\\n\");\n}\n"],"mappings":";;;;;;;AAQA,eAAsB,oBAAoB,QAEtB;AAClB,QAAM,YAAY,MAAM,cAAiB;AAEzC,MAAI,OAAO,WAAW,QAAQ;AAC5B,WAAO,KAAK,UAAU,WAAW,MAAM,CAAC;AAAA,EAC1C;AAEA,MAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,UAAU,WAAW,GAAG;AACvD,WAAO;AAAA,EACT;AAEA,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,gBAAgB,UAAU,MAAM;AAAA,CAAW;AAEtD,aAAW,KAAK,WAAW;AACzB,UAAM,KAAK,MAAM,EAAE,IAAI,EAAE;AACzB,UAAM,KAAK,WAAW,EAAE,EAAE,EAAE;AAC5B,UAAM,UACJ,EAAE,aAAa,EAAE,UAAU,SAAS,KAChC,EAAE,UAAU,MAAM,GAAG,EAAE,IAAI,QAC3B,EAAE;AACR,UAAM,KAAK,kBAAkB,OAAO,EAAE;AACtC,UAAM;AAAA,MACJ,iBAAiB,MAAM,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,SAAS,CAAC;AAAA,IACpE;AACA,QAAI,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,SAAS,GAAG;AAClD,YAAM,KAAK,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,IACjD;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-ZXKLPC2E.js";
4
4
  import {
5
5
  searchTraces
6
- } from "./chunk-HOPTUDCZ.js";
6
+ } from "./chunk-JVWDWL3J.js";
7
7
  import "./chunk-AAQNA53E.js";
8
8
 
9
9
  // src/tools/search-traces.ts
@@ -69,4 +69,4 @@ async function handleSearchTraces(params) {
69
69
  export {
70
70
  handleSearchTraces
71
71
  };
72
- //# sourceMappingURL=search-traces-RW2NDHN5.js.map
72
+ //# sourceMappingURL=search-traces-RSMYCAN7.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPromptVersion,
3
3
  updatePrompt
4
- } from "./chunk-HOPTUDCZ.js";
4
+ } from "./chunk-JVWDWL3J.js";
5
5
  import "./chunk-AAQNA53E.js";
6
6
 
7
7
  // src/tools/update-prompt.ts
@@ -28,4 +28,4 @@ async function handleUpdatePrompt(params) {
28
28
  export {
29
29
  handleUpdatePrompt
30
30
  };
31
- //# sourceMappingURL=update-prompt-G6HHZSUM.js.map
31
+ //# sourceMappingURL=update-prompt-G2Y5EBQY.js.map
@@ -0,0 +1,27 @@
1
+ import {
2
+ updateScenario
3
+ } from "./chunk-K2YFPOSD.js";
4
+ import "./chunk-JVWDWL3J.js";
5
+ import "./chunk-AAQNA53E.js";
6
+
7
+ // src/tools/update-scenario.ts
8
+ async function handleUpdateScenario(params) {
9
+ const { scenarioId, ...data } = params;
10
+ const result = await updateScenario({ id: scenarioId, ...data });
11
+ const lines = [];
12
+ lines.push("Scenario updated successfully!\n");
13
+ lines.push(`**ID**: ${result.id}`);
14
+ lines.push(`**Name**: ${result.name}`);
15
+ if (result.situation) lines.push(`**Situation**: ${result.situation}`);
16
+ if (Array.isArray(result.criteria) && result.criteria.length > 0) {
17
+ lines.push(`**Criteria**: ${result.criteria.length} criteria`);
18
+ }
19
+ if (Array.isArray(result.labels) && result.labels.length > 0) {
20
+ lines.push(`**Labels**: ${result.labels.join(", ")}`);
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+ export {
25
+ handleUpdateScenario
26
+ };
27
+ //# sourceMappingURL=update-scenario-SSGVOBJO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/update-scenario.ts"],"sourcesContent":["import { updateScenario as apiUpdateScenario } from \"../langwatch-api-scenarios.js\";\n\n/**\n * Handles the update_scenario MCP tool invocation.\n *\n * Updates an existing scenario and returns a confirmation\n * with the updated details.\n */\nexport async function handleUpdateScenario(params: {\n scenarioId: string;\n name?: string;\n situation?: string;\n criteria?: string[];\n labels?: string[];\n}): Promise<string> {\n const { scenarioId, ...data } = params;\n const result = await apiUpdateScenario({ id: scenarioId, ...data });\n\n const lines: string[] = [];\n lines.push(\"Scenario updated successfully!\\n\");\n lines.push(`**ID**: ${result.id}`);\n lines.push(`**Name**: ${result.name}`);\n if (result.situation) lines.push(`**Situation**: ${result.situation}`);\n if (Array.isArray(result.criteria) && result.criteria.length > 0) {\n lines.push(`**Criteria**: ${result.criteria.length} criteria`);\n }\n if (Array.isArray(result.labels) && result.labels.length > 0) {\n lines.push(`**Labels**: ${result.labels.join(\", \")}`);\n }\n\n return lines.join(\"\\n\");\n}\n"],"mappings":";;;;;;;AAQA,eAAsB,qBAAqB,QAMvB;AAClB,QAAM,EAAE,YAAY,GAAG,KAAK,IAAI;AAChC,QAAM,SAAS,MAAM,eAAkB,EAAE,IAAI,YAAY,GAAG,KAAK,CAAC;AAElE,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,kCAAkC;AAC7C,QAAM,KAAK,WAAW,OAAO,EAAE,EAAE;AACjC,QAAM,KAAK,aAAa,OAAO,IAAI,EAAE;AACrC,MAAI,OAAO,UAAW,OAAM,KAAK,kBAAkB,OAAO,SAAS,EAAE;AACrE,MAAI,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,SAAS,SAAS,GAAG;AAChE,UAAM,KAAK,iBAAiB,OAAO,SAAS,MAAM,WAAW;AAAA,EAC/D;AACA,MAAI,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,SAAS,GAAG;AAC5D,UAAM,KAAK,eAAe,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,EACtD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langwatch/mcp-server",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "An MCP server for Langwatch.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@ai-sdk/anthropic": "^2.0.15",
27
- "@anthropic-ai/claude-code": "^1.0.111",
27
+ "@anthropic-ai/claude-code": "^2.1.7",
28
28
  "@eslint/js": "^9.4.0",
29
29
  "@langwatch/scenario": "^0.3.0",
30
30
  "@types/debug": "^4.1.12",
@@ -34,7 +34,7 @@
34
34
  "@typescript/native-preview": "7.0.0-dev.20250911.1",
35
35
  "ai": "^5.0.40",
36
36
  "dotenv": "^17.2.2",
37
- "esbuild": "^0.21.5",
37
+ "esbuild": "^0.25.0",
38
38
  "eslint": "^8.57.0",
39
39
  "tsup": "^8.1.0",
40
40
  "tsx": "^4.20.5",
@@ -0,0 +1,286 @@
1
+ import { createServer, type Server } from "http";
2
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
+ import { initConfig } from "../config.js";
4
+
5
+ // --- Canned responses for scenario API endpoints ---
6
+
7
+ const CANNED_SCENARIOS_LIST = [
8
+ {
9
+ id: "scen_abc123",
10
+ name: "Login Flow Happy Path",
11
+ situation: "User attempts to log in with valid credentials",
12
+ criteria: ["Responds with a welcome message", "Includes user name in greeting"],
13
+ labels: ["auth", "happy-path"],
14
+ },
15
+ {
16
+ id: "scen_def456",
17
+ name: "Password Reset",
18
+ situation: "User requests a password reset link",
19
+ criteria: ["Sends reset email"],
20
+ labels: ["auth"],
21
+ },
22
+ ];
23
+
24
+ const CANNED_SCENARIO_DETAIL = {
25
+ id: "scen_abc123",
26
+ name: "Login Flow Happy Path",
27
+ situation: "User attempts to log in with valid credentials",
28
+ criteria: ["Responds with a welcome message", "Includes user name in greeting"],
29
+ labels: ["auth", "happy-path"],
30
+ };
31
+
32
+ const CANNED_SCENARIO_CREATED = {
33
+ id: "scen_new789",
34
+ name: "Login Flow Happy Path",
35
+ situation: "User attempts to log in with valid creds",
36
+ criteria: ["Responds with a welcome message", "Includes user name in greeting"],
37
+ labels: ["auth", "happy-path"],
38
+ };
39
+
40
+ const CANNED_SCENARIO_UPDATED = {
41
+ id: "scen_abc123",
42
+ name: "Login Flow - Valid Credentials",
43
+ situation: "User logs in with correct email and pass",
44
+ criteria: [
45
+ "Responds with welcome message",
46
+ "Sets session cookie",
47
+ "Redirects to dashboard",
48
+ ],
49
+ labels: ["auth", "happy-path"],
50
+ };
51
+
52
+ const CANNED_SCENARIO_ARCHIVED = {
53
+ id: "scen_abc123",
54
+ archived: true,
55
+ };
56
+
57
+ // --- Mock HTTP Server ---
58
+
59
+ function createMockServer(): Server {
60
+ return createServer((req, res) => {
61
+ const authToken = req.headers["x-auth-token"];
62
+ if (authToken !== "test-integration-key") {
63
+ res.writeHead(401, { "Content-Type": "application/json" });
64
+ res.end(JSON.stringify({ message: "Invalid auth token." }));
65
+ return;
66
+ }
67
+
68
+ let body = "";
69
+ req.on("data", (chunk: string) => (body += chunk));
70
+ req.on("end", () => {
71
+ const url = req.url ?? "";
72
+ res.setHeader("Content-Type", "application/json");
73
+
74
+ // GET /api/scenarios - list all scenarios
75
+ if (url === "/api/scenarios" && req.method === "GET") {
76
+ res.writeHead(200);
77
+ res.end(JSON.stringify(CANNED_SCENARIOS_LIST));
78
+ }
79
+ // GET /api/scenarios/:id - get scenario detail
80
+ else if (
81
+ url.match(/^\/api\/scenarios\/scen_abc123(\?|$)/) &&
82
+ req.method === "GET"
83
+ ) {
84
+ res.writeHead(200);
85
+ res.end(JSON.stringify(CANNED_SCENARIO_DETAIL));
86
+ }
87
+ // GET /api/scenarios/:id - not found
88
+ else if (
89
+ url.match(/^\/api\/scenarios\/scen_nonexistent(\?|$)/) &&
90
+ req.method === "GET"
91
+ ) {
92
+ res.writeHead(404);
93
+ res.end(JSON.stringify({ message: "Scenario not found" }));
94
+ }
95
+ // POST /api/scenarios - create scenario
96
+ else if (url === "/api/scenarios" && req.method === "POST") {
97
+ const parsed = JSON.parse(body);
98
+ if (!parsed.name) {
99
+ res.writeHead(400);
100
+ res.end(JSON.stringify({ message: "Validation error: name is required" }));
101
+ } else {
102
+ res.writeHead(201);
103
+ res.end(JSON.stringify(CANNED_SCENARIO_CREATED));
104
+ }
105
+ }
106
+ // PUT /api/scenarios/:id - update scenario
107
+ else if (
108
+ url.match(/^\/api\/scenarios\/scen_abc123$/) &&
109
+ req.method === "PUT"
110
+ ) {
111
+ res.writeHead(200);
112
+ res.end(JSON.stringify(CANNED_SCENARIO_UPDATED));
113
+ }
114
+ // PUT /api/scenarios/:id - not found
115
+ else if (
116
+ url.match(/^\/api\/scenarios\/scen_nonexistent$/) &&
117
+ req.method === "PUT"
118
+ ) {
119
+ res.writeHead(404);
120
+ res.end(JSON.stringify({ message: "Scenario not found" }));
121
+ }
122
+ // DELETE /api/scenarios/:id - archive scenario
123
+ else if (
124
+ url.match(/^\/api\/scenarios\/scen_abc123$/) &&
125
+ req.method === "DELETE"
126
+ ) {
127
+ res.writeHead(200);
128
+ res.end(JSON.stringify(CANNED_SCENARIO_ARCHIVED));
129
+ }
130
+ else {
131
+ res.writeHead(404);
132
+ res.end(
133
+ JSON.stringify({ message: `Not found: ${req.method} ${url}` })
134
+ );
135
+ }
136
+ });
137
+ });
138
+ }
139
+
140
+ // --- Integration Tests ---
141
+ // These verify that MCP tool handlers correctly communicate with the REST API
142
+ // (auth, HTTP methods, status codes, error propagation).
143
+ // Formatting/digest logic is tested in scenario-tools.unit.test.ts.
144
+
145
+ describe("MCP scenario tools integration", () => {
146
+ let server: Server;
147
+ let port: number;
148
+
149
+ beforeAll(async () => {
150
+ server = createMockServer();
151
+ await new Promise<void>((resolve) => {
152
+ server.listen(0, () => {
153
+ const addr = server.address();
154
+ port = typeof addr === "object" && addr ? addr.port : 0;
155
+ initConfig({
156
+ apiKey: "test-integration-key",
157
+ endpoint: `http://localhost:${port}`,
158
+ });
159
+ resolve();
160
+ });
161
+ });
162
+ });
163
+
164
+ afterAll(async () => {
165
+ await new Promise<void>((resolve) => server.close(() => resolve()));
166
+ });
167
+
168
+ describe("list_scenarios", () => {
169
+ describe("when the API returns scenarios", () => {
170
+ it("returns a non-empty result", async () => {
171
+ const { handleListScenarios } = await import(
172
+ "../tools/list-scenarios.js"
173
+ );
174
+ const result = await handleListScenarios({});
175
+ expect(result.length).toBeGreaterThan(0);
176
+ });
177
+ });
178
+
179
+ describe("when format is json", () => {
180
+ it("returns parseable JSON matching the API response", async () => {
181
+ const { handleListScenarios } = await import(
182
+ "../tools/list-scenarios.js"
183
+ );
184
+ const result = await handleListScenarios({ format: "json" });
185
+ expect(JSON.parse(result)).toEqual(CANNED_SCENARIOS_LIST);
186
+ });
187
+ });
188
+ });
189
+
190
+ describe("get_scenario", () => {
191
+ describe("when the scenario exists", () => {
192
+ it("returns a non-empty result", async () => {
193
+ const { handleGetScenario } = await import(
194
+ "../tools/get-scenario.js"
195
+ );
196
+ const result = await handleGetScenario({ scenarioId: "scen_abc123" });
197
+ expect(result.length).toBeGreaterThan(0);
198
+ });
199
+ });
200
+
201
+ describe("when the scenario does not exist", () => {
202
+ it("propagates the 404 error", async () => {
203
+ const { handleGetScenario } = await import(
204
+ "../tools/get-scenario.js"
205
+ );
206
+ await expect(
207
+ handleGetScenario({ scenarioId: "scen_nonexistent" })
208
+ ).rejects.toThrow("404");
209
+ });
210
+ });
211
+ });
212
+
213
+ describe("create_scenario", () => {
214
+ describe("when valid data is provided", () => {
215
+ it("returns confirmation with new scenario ID", async () => {
216
+ const { handleCreateScenario } = await import(
217
+ "../tools/create-scenario.js"
218
+ );
219
+ const result = await handleCreateScenario({
220
+ name: "Login Flow Happy Path",
221
+ situation: "User attempts to log in with valid creds",
222
+ criteria: ["Responds with a welcome message", "Includes user name in greeting"],
223
+ labels: ["auth", "happy-path"],
224
+ });
225
+ expect(result).toContain("scen_new789");
226
+ });
227
+ });
228
+
229
+ describe("when name is empty", () => {
230
+ it("propagates the validation error", async () => {
231
+ const { handleCreateScenario } = await import(
232
+ "../tools/create-scenario.js"
233
+ );
234
+ await expect(
235
+ handleCreateScenario({
236
+ name: "",
237
+ situation: "Some situation",
238
+ })
239
+ ).rejects.toThrow();
240
+ });
241
+ });
242
+ });
243
+
244
+ describe("update_scenario", () => {
245
+ describe("when the scenario exists", () => {
246
+ it("returns a non-empty result", async () => {
247
+ const { handleUpdateScenario } = await import(
248
+ "../tools/update-scenario.js"
249
+ );
250
+ const result = await handleUpdateScenario({
251
+ scenarioId: "scen_abc123",
252
+ name: "Login Flow - Valid Credentials",
253
+ });
254
+ expect(result.length).toBeGreaterThan(0);
255
+ });
256
+ });
257
+
258
+ describe("when the scenario does not exist", () => {
259
+ it("propagates the 404 error", async () => {
260
+ const { handleUpdateScenario } = await import(
261
+ "../tools/update-scenario.js"
262
+ );
263
+ await expect(
264
+ handleUpdateScenario({
265
+ scenarioId: "scen_nonexistent",
266
+ name: "Updated Name",
267
+ })
268
+ ).rejects.toThrow("404");
269
+ });
270
+ });
271
+ });
272
+
273
+ describe("archive_scenario", () => {
274
+ describe("when the scenario exists", () => {
275
+ it("returns confirmation that scenario was archived", async () => {
276
+ const { handleArchiveScenario } = await import(
277
+ "../tools/archive-scenario.js"
278
+ );
279
+ const result = await handleArchiveScenario({
280
+ scenarioId: "scen_abc123",
281
+ });
282
+ expect(result).toContain("archived");
283
+ });
284
+ });
285
+ });
286
+ });