@qulib/mcp 0.5.3 → 0.7.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.
@@ -0,0 +1,12 @@
1
+ import type { AnalyzeResult } from '@qulib/core';
2
+ export interface AnalyzeAppMcpPayloadOptions {
3
+ includeFullReport?: boolean;
4
+ /** When true, returns only `toAgentSummary(result)` JSON (QLIB-001). Ignores `includeFullReport`. */
5
+ agentSummary?: boolean;
6
+ }
7
+ /**
8
+ * Single place for analyze_app response shaping: default summary-first,
9
+ * optional full report, or compact agent gate summary.
10
+ */
11
+ export declare function buildAnalyzeAppMcpPayload(result: AnalyzeResult, input: AnalyzeAppMcpPayloadOptions): unknown;
12
+ //# sourceMappingURL=analyze-app-mcp-payload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-app-mcp-payload.d.ts","sourceRoot":"","sources":["../src/analyze-app-mcp-payload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,MAAM,WAAW,2BAA2B;IAC1C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qGAAqG;IACrG,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAKT"}
@@ -0,0 +1,12 @@
1
+ import { toAgentSummary } from '@qulib/core';
2
+ import { summarizeAnalyzeResult } from './summarize-analyze-result.js';
3
+ /**
4
+ * Single place for analyze_app response shaping: default summary-first,
5
+ * optional full report, or compact agent gate summary.
6
+ */
7
+ export function buildAnalyzeAppMcpPayload(result, input) {
8
+ if (input.agentSummary === true) {
9
+ return toAgentSummary(result);
10
+ }
11
+ return summarizeAnalyzeResult(result, input.includeFullReport === true);
12
+ }
package/dist/index.js CHANGED
@@ -14,9 +14,9 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
14
14
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
15
15
  const requirePkg = createRequire(import.meta.url);
16
16
  const pkg = requirePkg('../package.json');
17
- import { analyzeApp, detectAuth, exploreAuth, scanRepo, computeAutomationMaturity, } from '@qulib/core';
17
+ import { analyzeApp, detectAuth, exploreAuth, scanRepo, computeAutomationMaturity, scaffoldTests, } from '@qulib/core';
18
18
  import { z } from 'zod';
19
- import { summarizeAnalyzeResult } from './summarize-analyze-result.js';
19
+ import { buildAnalyzeAppMcpPayload } from './analyze-app-mcp-payload.js';
20
20
  import { log } from './logger.js';
21
21
  function toolError(code, message, detail) {
22
22
  return {
@@ -68,6 +68,10 @@ const AnalyzeInputSchema = z.object({
68
68
  timeoutMs: z.number().int().positive().optional(),
69
69
  auth: z.discriminatedUnion('type', [FormLoginMcpAuthSchema, StorageStateMcpAuthSchema]).optional(),
70
70
  includeFullReport: z.boolean().optional(),
71
+ agentSummary: z
72
+ .boolean()
73
+ .optional()
74
+ .describe('When true, return only the versioned agent-summary JSON ({ schemaVersion: 1, gate, coverageStatus, topRisks, recommendedNextChecks, honestyNotes, costSummary, deterministicFollowUps }). Use this for CI gates and orchestrators that need a single small payload to decide pass/warn/fail. Overrides includeFullReport.'),
71
75
  llmTokenBudget: z.number().int().positive().optional(),
72
76
  llmMaxOutputTokensPerCall: z.number().int().positive().optional(),
73
77
  testGenerationLimit: z.number().int().positive().max(50).optional(),
@@ -153,7 +157,7 @@ mcpServer.registerTool('detect_auth', {
153
157
  }
154
158
  });
155
159
  mcpServer.registerTool('analyze_app', {
156
- description: 'Analyze a deployed web app for quality gaps. Default response is summary-first (top gaps, cost summary, next checks). Set includeFullReport for the full gapAnalysis. Optional llmMaxOutputTokensPerCall / llmTokenBudget (legacy), testGenerationLimit, enableLlmScenarios align with @qulib/core HarnessConfig.',
160
+ description: 'Analyze a deployed web app for quality gaps. Default response is summary-first (top gaps, cost summary, next checks). Set includeFullReport for the full gapAnalysis. Set agentSummary for the compact gate-decision payload (pass/warn/fail with honesty notes) — use this when calling from a CI gate or orchestrator. Optional llmMaxOutputTokensPerCall / llmTokenBudget (legacy), testGenerationLimit, enableLlmScenarios align with @qulib/core HarnessConfig.',
157
161
  inputSchema: AnalyzeInputSchema,
158
162
  }, async (input) => {
159
163
  try {
@@ -202,7 +206,10 @@ mcpServer.registerTool('analyze_app', {
202
206
  progressLog: mcpProgressLog,
203
207
  telemetry: telemetrySink,
204
208
  });
205
- const payload = summarizeAnalyzeResult(result, input.includeFullReport === true);
209
+ const payload = buildAnalyzeAppMcpPayload(result, {
210
+ includeFullReport: input.includeFullReport,
211
+ agentSummary: input.agentSummary,
212
+ });
206
213
  return {
207
214
  content: [
208
215
  {
@@ -254,5 +261,53 @@ mcpServer.registerTool('qulib_score_automation', {
254
261
  return toolError('QULIB_REPO_SCORE_FAILED', msg, err instanceof Error ? err.stack : undefined);
255
262
  }
256
263
  });
264
+ const ScaffoldTestsInputSchema = z.object({
265
+ url: z.string().url().describe('URL of the deployed web app to scaffold tests for'),
266
+ framework: z
267
+ .enum(['cypress-e2e', 'playwright'])
268
+ .optional()
269
+ .describe('Test framework to generate. Default: cypress-e2e'),
270
+ maxPagesToScan: z
271
+ .number()
272
+ .int()
273
+ .min(1)
274
+ .max(20)
275
+ .optional()
276
+ .describe('Max pages to crawl when running analyze_app internally. Default: 10'),
277
+ });
278
+ mcpServer.registerTool('qulib_scaffold_tests', {
279
+ description: 'Generate a ready-to-run test scaffold for a deployed web app. Crawls the URL, identifies quality gaps and user flows, then produces framework-specific test files (Cypress or Playwright) plus the project config (cypress.config.ts or playwright.config.ts) and package.json deps. Returns generatedTests (array of {filename, code, outputPath}) and projectConfig so an agent can write the files directly to a repo without any manual test-writing.',
280
+ inputSchema: ScaffoldTestsInputSchema,
281
+ }, async ({ url, framework, maxPagesToScan }) => {
282
+ try {
283
+ log.info(`qulib_scaffold_tests url=${url} framework=${framework ?? 'cypress-e2e'} maxPagesToScan=${maxPagesToScan ?? 10}`);
284
+ const result = await scaffoldTests(url, {
285
+ framework: framework ?? 'cypress-e2e',
286
+ maxPagesToScan: maxPagesToScan ?? 10,
287
+ progressLog: mcpProgressLog,
288
+ telemetry: telemetrySink,
289
+ });
290
+ return {
291
+ content: [
292
+ {
293
+ type: 'text',
294
+ text: JSON.stringify({
295
+ url: result.url,
296
+ framework: result.framework,
297
+ scenarioCount: result.scenarios.length,
298
+ testCount: result.generatedTests.length,
299
+ generatedTests: result.generatedTests,
300
+ projectConfig: result.projectConfig,
301
+ }, null, 2),
302
+ },
303
+ ],
304
+ };
305
+ }
306
+ catch (err) {
307
+ const msg = err instanceof Error ? err.message : String(err);
308
+ log.error(`qulib_scaffold_tests failed: ${msg}`);
309
+ return toolError('QULIB_SCAFFOLD_FAILED', msg, err instanceof Error ? err.stack : undefined);
310
+ }
311
+ });
257
312
  const transport = new StdioServerTransport();
258
313
  await mcpServer.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qulib/mcp",
3
- "version": "0.5.3",
3
+ "version": "0.7.0",
4
4
  "description": "MCP server for Qulib — AI-callable QA gap analysis",
5
5
  "license": "MIT",
6
6
  "author": "Tapesh Nagarwal",
@@ -29,11 +29,11 @@
29
29
  "scripts": {
30
30
  "build": "npm --prefix ../.. run build -w @qulib/core && tsc && chmod +x dist/index.js",
31
31
  "dev": "tsx src/index.ts",
32
- "test": "node --import tsx/esm --test src/__tests__/summarize-analyze-result.test.ts"
32
+ "test": "node --import tsx/esm --test src/__tests__/summarize-analyze-result.test.ts src/__tests__/analyze-app-mcp-payload.test.ts"
33
33
  },
34
34
  "dependencies": {
35
35
  "@modelcontextprotocol/sdk": "^1.0.0",
36
- "@qulib/core": "0.5.3",
36
+ "@qulib/core": "0.7.0",
37
37
  "zod": "^3.23.0"
38
38
  },
39
39
  "devDependencies": {