@qulib/mcp 0.5.1 → 0.5.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qulib/mcp",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "MCP server for Qulib — AI-callable QA gap analysis",
5
5
  "license": "MIT",
6
6
  "author": "Tapesh Nagarwal",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@modelcontextprotocol/sdk": "^1.0.0",
36
- "@qulib/core": "0.5.1",
36
+ "@qulib/core": "0.5.3",
37
37
  "zod": "^3.23.0"
38
38
  },
39
39
  "devDependencies": {
@@ -1,164 +0,0 @@
1
- import type { AnalyzeResult } from '@qulib/core';
2
- export declare function buildCompactAnalyzePayload(result: AnalyzeResult, includeFullReport: boolean): AnalyzeResult | {
3
- includeFullReport: boolean;
4
- note: string;
5
- detectedAuth?: {
6
- type: "unknown" | "form-login" | "oauth" | "magic-link" | "none";
7
- loginUrl: string | null;
8
- provider: string | null;
9
- hasAuth: boolean;
10
- observedSelectors: {
11
- usernameSelector: string | null;
12
- passwordSelector: string | null;
13
- submitSelector: string | null;
14
- } | null;
15
- oauthButtons: {
16
- text: string;
17
- provider: string;
18
- }[];
19
- recommendation: string;
20
- authOptions?: {
21
- type: "unknown" | "form-login" | "oauth" | "oauth-unknown" | "form-multi" | "magic-link";
22
- label: string;
23
- id: string;
24
- provider: string | null;
25
- source: "built-in" | "user-local" | "heuristic";
26
- automatable: boolean;
27
- confidence: "high" | "medium" | "low";
28
- requirements: {
29
- method: "storage-state";
30
- instruction: string;
31
- } | {
32
- method: "credentials";
33
- fields: {
34
- type: "password" | "text" | "email" | "select" | "checkbox";
35
- name: string;
36
- label: string;
37
- observedOptions: string[];
38
- }[];
39
- } | {
40
- method: "unknown";
41
- instruction: string;
42
- };
43
- }[] | undefined;
44
- } | undefined;
45
- repoInventorySummary: {
46
- framework?: {
47
- primary: "unknown" | "nextjs-app-router" | "nextjs-pages-router" | "express" | "remix" | "nuxt" | "sveltekit" | "astro" | "vite";
48
- confidence: "high" | "medium" | "low";
49
- testFrameworks: ("playwright" | "cypress-e2e" | "cypress-component" | "jest" | "vitest" | "other")[];
50
- evidenceCount: number;
51
- } | undefined;
52
- repoPath: string;
53
- scannedAt: string;
54
- routeCount: number;
55
- testFileCount: number;
56
- missingTestIdCount: number;
57
- interactiveTsxFilesScanned: number | null;
58
- cypressDetected: boolean;
59
- } | null;
60
- decisionLogPreview: {
61
- timestamp: string;
62
- reason: string;
63
- phase: "observe" | "think" | "act" | "harness";
64
- decision: string;
65
- metadata?: Record<string, unknown> | undefined;
66
- }[];
67
- automationMaturitySummary?: {
68
- overallScore: number;
69
- level: number;
70
- label: string;
71
- topRecommendations: string[];
72
- } | undefined;
73
- summary: {
74
- status: import("@qulib/core").AnalyzeStatus;
75
- coverageScore: number | null;
76
- releaseConfidence: number | null;
77
- mode: "url-only" | "url-repo" | "auth-required";
78
- coveragePagesScanned: number;
79
- coverageBudgetExceeded: boolean;
80
- coverageWarning: "auth-required" | "budget-exceeded" | "low-coverage" | "navigation-failures" | null;
81
- gapCount: number;
82
- scenarioCount: number;
83
- generatedTestCount: number;
84
- publicSurface: {
85
- pageCount: number;
86
- gapCount: number;
87
- accessibilityViolationCount: number;
88
- brokenLinkCount: number;
89
- } | null;
90
- };
91
- topGaps: {
92
- path: string;
93
- category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage";
94
- severity: "critical" | "high" | "medium" | "low";
95
- reason: string;
96
- }[];
97
- costIntelligenceSummary: {
98
- maxOutputTokensPerLlmCall: number;
99
- usageDataQuality: "none" | "actual" | "estimated" | "mixed";
100
- totalInputTokens: number;
101
- totalOutputTokens: number;
102
- budgetWarningCount: number;
103
- maturityLevel: number;
104
- maturityLabel: string;
105
- } | null;
106
- costIntelligence: {
107
- maxOutputTokensPerLlmCall: number;
108
- budgetRole: "max-output-tokens-per-llm-call";
109
- records: {
110
- provider: string;
111
- model: string;
112
- inputTokens: number;
113
- outputTokens: number;
114
- operationType: "scenario-generation";
115
- timestamp: string;
116
- dataQuality: "none" | "actual" | "estimated" | "mixed";
117
- estimatedCostUsd?: number | undefined;
118
- promptHash?: string | undefined;
119
- resultHash?: string | undefined;
120
- notes?: string | undefined;
121
- }[];
122
- budgetWarnings: string[];
123
- usageSummary: {
124
- dataQuality: "none" | "actual" | "estimated" | "mixed";
125
- totalInputTokens: number;
126
- totalOutputTokens: number;
127
- };
128
- repeatedOperations: {
129
- recommendation: string;
130
- promptHash: string;
131
- count: number;
132
- }[];
133
- deterministicMaturity: {
134
- label: string;
135
- level: number;
136
- rationale: string;
137
- ceilingNote?: string | undefined;
138
- };
139
- conversionRecommendations: string[];
140
- } | null;
141
- nextDeterministicChecks: string[];
142
- gapAnalysisPreview: {
143
- analyzedAt: string;
144
- gapsSample: {
145
- path: string;
146
- id: string;
147
- severity: "critical" | "high" | "medium" | "low";
148
- reason: string;
149
- category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage";
150
- recommendation?: string | undefined;
151
- description?: string | undefined;
152
- }[];
153
- scenariosOmitted: number;
154
- generatedTestsOmitted: number;
155
- };
156
- routeInventorySummary: {
157
- scannedAt: string;
158
- baseUrl: string;
159
- routeCount: number;
160
- pagesSkipped: number;
161
- budgetExceeded: boolean;
162
- };
163
- };
164
- //# sourceMappingURL=compact-analyze-payload.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compact-analyze-payload.d.ts","sourceRoot":"","sources":["../src/compact-analyze-payload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqBjD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAuG+9d,CAAC;sBAA4C,CAAC;sBAA4C,CAAC;iBAAuC,CAAC;;;;;;;;;;;;;;;;;uBAAghB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;EAD9sf"}
@@ -1,115 +0,0 @@
1
- const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
2
- function topGapsBySeverity(gaps, limit) {
3
- return [...gaps].sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]).slice(0, limit);
4
- }
5
- function nextDeterministicChecks(gaps, conversion) {
6
- const out = [];
7
- const byCat = new Map();
8
- for (const g of gaps) {
9
- byCat.set(g.category, (byCat.get(g.category) ?? 0) + 1);
10
- }
11
- for (const [cat, n] of [...byCat.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3)) {
12
- out.push(`Add or tighten deterministic coverage for **${cat}** (${n} gap(s) in this scan).`);
13
- }
14
- out.push(...conversion.slice(0, 2));
15
- return out.slice(0, 5);
16
- }
17
- export function buildCompactAnalyzePayload(result, includeFullReport) {
18
- if (includeFullReport) {
19
- return result;
20
- }
21
- const g = result.gapAnalysis;
22
- const ci = g.costIntelligence;
23
- const top = topGapsBySeverity(result.gaps, 5);
24
- const costSummary = ci
25
- ? {
26
- maxOutputTokensPerLlmCall: ci.maxOutputTokensPerLlmCall,
27
- usageDataQuality: ci.usageSummary.dataQuality,
28
- totalInputTokens: ci.usageSummary.totalInputTokens,
29
- totalOutputTokens: ci.usageSummary.totalOutputTokens,
30
- budgetWarningCount: ci.budgetWarnings.length,
31
- maturityLevel: ci.deterministicMaturity.level,
32
- maturityLabel: ci.deterministicMaturity.label,
33
- }
34
- : null;
35
- const ps = result.publicSurface;
36
- const repo = result.repoInventory;
37
- const repoInventorySummary = repo
38
- ? {
39
- repoPath: repo.repoPath,
40
- scannedAt: repo.scannedAt,
41
- routeCount: repo.routes.length,
42
- testFileCount: repo.testFiles.length,
43
- missingTestIdCount: repo.missingTestIds.length,
44
- interactiveTsxFilesScanned: repo.interactiveTsxFilesScanned ?? null,
45
- cypressDetected: repo.cypressStructure.detected,
46
- ...(repo.framework && {
47
- framework: {
48
- primary: repo.framework.primary,
49
- confidence: repo.framework.confidence,
50
- testFrameworks: repo.framework.testFrameworks,
51
- evidenceCount: repo.framework.evidence.length,
52
- },
53
- }),
54
- }
55
- : null;
56
- return {
57
- summary: {
58
- status: result.status,
59
- coverageScore: result.coverageScore,
60
- releaseConfidence: g.releaseConfidence,
61
- mode: g.mode,
62
- coveragePagesScanned: g.coveragePagesScanned,
63
- coverageBudgetExceeded: g.coverageBudgetExceeded,
64
- coverageWarning: g.coverageWarning ?? null,
65
- gapCount: g.gaps.length,
66
- scenarioCount: g.scenarios.length,
67
- generatedTestCount: g.generatedTests.length,
68
- publicSurface: ps === null
69
- ? null
70
- : {
71
- pageCount: ps.pages.length,
72
- gapCount: ps.gaps.length,
73
- accessibilityViolationCount: ps.accessibilityViolations.length,
74
- brokenLinkCount: ps.brokenLinks.length,
75
- },
76
- },
77
- topGaps: top.map((x) => ({
78
- path: x.path,
79
- category: x.category,
80
- severity: x.severity,
81
- reason: x.reason,
82
- })),
83
- costIntelligenceSummary: costSummary,
84
- costIntelligence: ci ?? null,
85
- nextDeterministicChecks: ci
86
- ? nextDeterministicChecks(result.gaps, ci.conversionRecommendations)
87
- : nextDeterministicChecks(result.gaps, []),
88
- gapAnalysisPreview: {
89
- analyzedAt: g.analyzedAt,
90
- gapsSample: g.gaps.slice(0, 8),
91
- scenariosOmitted: g.scenarios.length,
92
- generatedTestsOmitted: g.generatedTests.length,
93
- },
94
- routeInventorySummary: {
95
- scannedAt: result.routeInventory.scannedAt,
96
- baseUrl: result.routeInventory.baseUrl,
97
- routeCount: result.routeInventory.routes.length,
98
- pagesSkipped: result.routeInventory.pagesSkipped,
99
- budgetExceeded: result.routeInventory.budgetExceeded,
100
- },
101
- ...(repo?.automationMaturity && {
102
- automationMaturitySummary: {
103
- overallScore: repo.automationMaturity.overallScore,
104
- level: repo.automationMaturity.level,
105
- label: repo.automationMaturity.label,
106
- topRecommendations: repo.automationMaturity.topRecommendations,
107
- },
108
- }),
109
- repoInventorySummary,
110
- decisionLogPreview: result.decisionLog.slice(-8),
111
- ...(result.detectedAuth !== undefined && { detectedAuth: result.detectedAuth }),
112
- includeFullReport: false,
113
- note: 'Summary-first payload. Pass includeFullReport: true for the full gapAnalysis (all scenarios, generated tests) and the full repoInventory (test files, missing test IDs).',
114
- };
115
- }