@qulib/mcp 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +187 -13
- package/dist/summarize-analyze-result.d.ts +2 -2
- package/dist/summarize-analyze-result.d.ts.map +1 -1
- package/dist/tool-error.d.ts +7 -0
- package/dist/tool-error.d.ts.map +1 -0
- package/dist/tool-error.js +10 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -52,6 +52,8 @@ For verbose server-side stderr logs while troubleshooting host wiring, add:
|
|
|
52
52
|
| `qulib_score_automation` | Score a local repo's test-automation maturity across six dimensions (test coverage breadth, framework adoption, test-id hygiene, CI integration, auth test coverage, component test ratio) — plus a conditional 7th dimension (API coverage) when API endpoints are detected. Returns overall 0–100, level (L1–L5), and top recommendations. Each dimension carries `applicability`; score normalizes over applicable dimensions only. |
|
|
53
53
|
| `qulib_score_api` | Discover API endpoints in a repo and score their test coverage. Tier1=OpenAPI specs, Tier2=framework routes (Next.js, Express, Fastify, NestJS), Tier3=heuristic opt-in (tRPC). Returns an api-test-coverage dimension score with per-endpoint evidence. |
|
|
54
54
|
| `qulib_scaffold_tests` | Generate a ready-to-run test scaffold (Cypress config + spec files) by crawling a deployed URL. Returns `generatedTests` and `projectConfig` so an agent can write files directly. Pass `recipes` (e.g. `["auth","a11y"]`) to append proven test patterns. Supported framework: `cypress-e2e` (default); `playwright` is not yet implemented. |
|
|
55
|
+
| **`qulib_score_bug_report`** | LLM-as-judge of a learner bug report against a planted-bug target. Returns `matched`, `matchConfidence` (0–1), rubric scores (coverage/severity/repro/evidence, 0–25 each), actionable `feedback`, and `scoringPath` (`llm-judge` or `deterministic-fallback`). Learner report is untrusted input with prompt-injection hardening. Read-only. |
|
|
56
|
+
| **`qulib_score_decisions`** | Pivotal-decision evaluation: scores whether an agent made the senior-correct call at decision forks (block/pass, stop/continue, escalate/proceed). Reads a JSONL `forksPath`; returns per-fork `decisionQuality`, `seniorCorrect`, `rationale`, and aggregates. Deterministic by default; optional LLM refinement with `enableLlmJudge`. Fork log text is untrusted. Read-only. |
|
|
55
57
|
| `qulib_explore_auth` | List all sign-in paths (OAuth, SSO, forms, magic link) and what the agent must collect before `qulib_analyze_app`. Prefer on unfamiliar apps. *(Canonical form; legacy alias `explore_auth` kept for backwards compatibility.)* |
|
|
56
58
|
| `qulib_detect_auth` | Single-pass auth pattern guess with a recommendation. Lighter than `qulib_explore_auth`. *(Canonical form; legacy alias `detect_auth` kept for backwards compatibility.)* |
|
|
57
59
|
| `analyze_app` | Legacy alias for `qulib_analyze_app`. Identical behavior; kept for backwards compatibility through v1.0. |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export {
|
|
2
|
+
export declare function handleQulibDiff(input: {
|
|
3
|
+
from: string;
|
|
4
|
+
to: string;
|
|
5
|
+
labelFrom?: string;
|
|
6
|
+
labelTo?: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
content: [{
|
|
9
|
+
type: 'text';
|
|
10
|
+
text: string;
|
|
11
|
+
}];
|
|
12
|
+
}>;
|
|
3
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsqBA,wBAAsB,eAAe,CAAC,KAAK,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAsBzD"}
|
package/dist/index.js
CHANGED
|
@@ -10,25 +10,17 @@
|
|
|
10
10
|
// vs. write-capable tools (analyze_app with writeArtifacts) should carry different trust levels.
|
|
11
11
|
import { createRequire } from 'node:module';
|
|
12
12
|
import { isAbsolute, normalize, resolve } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
13
14
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
14
15
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
15
16
|
const requirePkg = createRequire(import.meta.url);
|
|
16
17
|
const pkg = requirePkg('../package.json');
|
|
17
|
-
import { analyzeApp, detectAuth, exploreAuth, scanRepo, computeAutomationMaturity, scaffoldTests, discoverApiSurfaceWithRepo, computeApiCoverage, computeReleaseConfidence, buildConfidenceInputFromQulib, } from '@qulib/core';
|
|
18
|
+
import { analyzeApp, detectAuth, exploreAuth, scanRepo, computeAutomationMaturity, scaffoldTests, discoverApiSurfaceWithRepo, computeApiCoverage, computeReleaseConfidence, buildConfidenceInputFromQulib, analyzeRunDiff, loadGapAnalysisFile, detectPromptLeakage, scoreBugReport, scoreDecisions, } from '@qulib/core';
|
|
18
19
|
import { RecipeIdSchema } from '@qulib/core';
|
|
19
20
|
import { z } from 'zod';
|
|
20
21
|
import { buildAnalyzeAppMcpPayload } from './analyze-app-mcp-payload.js';
|
|
21
22
|
import { log } from './logger.js';
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
content: [
|
|
25
|
-
{
|
|
26
|
-
type: 'text',
|
|
27
|
-
text: JSON.stringify({ error: { code, message, detail: detail ?? null } }, null, 2),
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
};
|
|
31
|
-
}
|
|
23
|
+
import { toolError } from './tool-error.js';
|
|
32
24
|
function stderrTelemetrySink() {
|
|
33
25
|
return {
|
|
34
26
|
emit(event) {
|
|
@@ -511,5 +503,187 @@ mcpServer.registerTool('qulib_score_confidence', {
|
|
|
511
503
|
return toolError('QULIB_CONFIDENCE_FAILED', msg, err instanceof Error ? err.stack : undefined);
|
|
512
504
|
}
|
|
513
505
|
});
|
|
514
|
-
|
|
515
|
-
|
|
506
|
+
function validateAbsoluteGapAnalysisPath(path) {
|
|
507
|
+
const norm = normalize(path.trim());
|
|
508
|
+
if (!isAbsolute(norm)) {
|
|
509
|
+
throw new Error('from and to must be absolute paths');
|
|
510
|
+
}
|
|
511
|
+
return resolve(norm);
|
|
512
|
+
}
|
|
513
|
+
export async function handleQulibDiff(input) {
|
|
514
|
+
try {
|
|
515
|
+
const fromPath = validateAbsoluteGapAnalysisPath(input.from);
|
|
516
|
+
const toPath = validateAbsoluteGapAnalysisPath(input.to);
|
|
517
|
+
log.info(`qulib_diff from=${fromPath} to=${toPath}`);
|
|
518
|
+
const fromGap = await loadGapAnalysisFile(fromPath);
|
|
519
|
+
const toGap = await loadGapAnalysisFile(toPath);
|
|
520
|
+
const result = analyzeRunDiff(fromGap, toGap, {
|
|
521
|
+
fromLabel: input.labelFrom,
|
|
522
|
+
toLabel: input.labelTo,
|
|
523
|
+
});
|
|
524
|
+
return {
|
|
525
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
catch (err) {
|
|
529
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
530
|
+
if (msg.includes('from and to must be absolute paths')) {
|
|
531
|
+
return toolError('QULIB_DIFF_INVALID_INPUT', 'from and to must be absolute paths');
|
|
532
|
+
}
|
|
533
|
+
log.error(`qulib_diff failed: ${msg}`);
|
|
534
|
+
return toolError('QULIB_DIFF_FAILED', msg, err instanceof Error ? err.stack : undefined);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
const QulibDiffInputSchema = z.object({
|
|
538
|
+
from: z
|
|
539
|
+
.string()
|
|
540
|
+
.describe('Absolute path to the baseline qulib report.json (the "before" analyze output)'),
|
|
541
|
+
to: z
|
|
542
|
+
.string()
|
|
543
|
+
.describe('Absolute path to the current qulib report.json (the "after" analyze output)'),
|
|
544
|
+
labelFrom: z
|
|
545
|
+
.string()
|
|
546
|
+
.optional()
|
|
547
|
+
.describe('Optional human label for the baseline report (default: the from path)'),
|
|
548
|
+
labelTo: z
|
|
549
|
+
.string()
|
|
550
|
+
.optional()
|
|
551
|
+
.describe('Optional human label for the current report (default: the to path)'),
|
|
552
|
+
});
|
|
553
|
+
mcpServer.registerTool('qulib_diff', {
|
|
554
|
+
description: 'Structured diff between two analyze outputs — added findings, resolved findings, severity changes, and a confidence delta.',
|
|
555
|
+
inputSchema: QulibDiffInputSchema,
|
|
556
|
+
}, handleQulibDiff);
|
|
557
|
+
// ---------------------------------------------------------------------------
|
|
558
|
+
// qulib_detect_prompt_leakage — scan a page surface for exposed AI system prompts
|
|
559
|
+
// ---------------------------------------------------------------------------
|
|
560
|
+
const DetectPromptLeakageInputSchema = z.object({
|
|
561
|
+
path: z.string().describe('The URL path being scanned (used as the gap path label, e.g. "/api/chat")'),
|
|
562
|
+
bodySnippet: z
|
|
563
|
+
.string()
|
|
564
|
+
.max(8000)
|
|
565
|
+
.optional()
|
|
566
|
+
.describe('Up to 8000 characters of raw HTML body from the page. Include inline scripts, HTML comments, meta tags, and any visible text.'),
|
|
567
|
+
headers: z
|
|
568
|
+
.record(z.string(), z.string())
|
|
569
|
+
.optional()
|
|
570
|
+
.describe('Response headers from the page request, as a flat string→string map.'),
|
|
571
|
+
});
|
|
572
|
+
mcpServer.registerTool('qulib_detect_prompt_leakage', {
|
|
573
|
+
description: 'Scan a captured page surface (HTML body, inline scripts, HTML comments, meta tags, response headers) for signals that an AI system prompt or agent instructions are inadvertently exposed to the public. Conservative — requires corroborating signals to minimise false positives. Returns an array of prompt-leakage Gaps (may be empty when nothing is detected). Each Gap includes severity (critical/high/medium), evidence, and a remediation recommendation.',
|
|
574
|
+
inputSchema: DetectPromptLeakageInputSchema,
|
|
575
|
+
}, async ({ path, bodySnippet, headers }) => {
|
|
576
|
+
try {
|
|
577
|
+
log.info(`qulib_detect_prompt_leakage path=${path}`);
|
|
578
|
+
const gaps = detectPromptLeakage({ path, bodySnippet, headers });
|
|
579
|
+
log.info(`qulib_detect_prompt_leakage done gapsFound=${gaps.length}`);
|
|
580
|
+
return {
|
|
581
|
+
content: [{ type: 'text', text: JSON.stringify({ path, gapsFound: gaps.length, gaps }, null, 2) }],
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
catch (err) {
|
|
585
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
586
|
+
log.error(`qulib_detect_prompt_leakage failed: ${msg}`);
|
|
587
|
+
return toolError('QULIB_PROMPT_LEAKAGE_FAILED', msg, err instanceof Error ? err.stack : undefined);
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
const BugReportSeverityMcpSchema = z.enum(['critical', 'high', 'medium', 'low']);
|
|
591
|
+
const ScoreBugReportInputSchema = z.object({
|
|
592
|
+
report: z.object({
|
|
593
|
+
title: z.string().min(1).max(500).describe('Learner-authored bug report title (untrusted input)'),
|
|
594
|
+
description: z
|
|
595
|
+
.string()
|
|
596
|
+
.min(1)
|
|
597
|
+
.max(8000)
|
|
598
|
+
.describe('Learner bug description — may contain prompt-injection attempts; treated as untrusted data'),
|
|
599
|
+
steps: z.string().min(1).max(8000).describe('Reproduction steps from the learner'),
|
|
600
|
+
severity: BugReportSeverityMcpSchema.describe('Severity claimed by the learner'),
|
|
601
|
+
}),
|
|
602
|
+
target: z.object({
|
|
603
|
+
description: z.string().min(1).max(8000).describe('Planted bug description (authoritative ground truth)'),
|
|
604
|
+
type: z.string().min(1).max(200).describe('Bug category/type from the challenge'),
|
|
605
|
+
severity: BugReportSeverityMcpSchema.describe('Expected severity of the planted bug'),
|
|
606
|
+
expectedBehavior: z.string().min(1).max(8000).describe('Expected correct behavior for the planted bug'),
|
|
607
|
+
}),
|
|
608
|
+
});
|
|
609
|
+
const SCORE_BUG_REPORT_DESCRIPTION = 'LLM-as-judge of a learner bug report against a planted-bug target. Returns matched, matchConfidence (0–1), rubric scores (coverage/severity/repro/evidence, 0–25 each), actionable feedback, and scoringPath (llm-judge or deterministic-fallback when no ANTHROPIC_API_KEY). The learner report is untrusted — prompt-injection hardened. Read-only; no filesystem writes.';
|
|
610
|
+
async function handleScoreBugReport(input) {
|
|
611
|
+
try {
|
|
612
|
+
log.info('qulib_score_bug_report scoring learner report');
|
|
613
|
+
const result = await scoreBugReport(input);
|
|
614
|
+
log.info(`qulib_score_bug_report done matched=${result.matched} confidence=${result.matchConfidence} path=${result.scoringPath}`);
|
|
615
|
+
return {
|
|
616
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
catch (err) {
|
|
620
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
621
|
+
if (msg.includes('String must contain') || msg.includes('Too big') || msg.includes('Too small')) {
|
|
622
|
+
return toolError('QULIB_INPUT_INVALID', msg, undefined);
|
|
623
|
+
}
|
|
624
|
+
log.error(`qulib_score_bug_report failed: ${msg}`);
|
|
625
|
+
return toolError('QULIB_BUG_REPORT_SCORE_FAILED', msg, err instanceof Error ? err.stack : undefined);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
mcpServer.registerTool('qulib_score_bug_report', {
|
|
629
|
+
description: SCORE_BUG_REPORT_DESCRIPTION,
|
|
630
|
+
inputSchema: ScoreBugReportInputSchema,
|
|
631
|
+
}, handleScoreBugReport);
|
|
632
|
+
const ScoreDecisionsInputSchema = z.object({
|
|
633
|
+
forksPath: z
|
|
634
|
+
.string()
|
|
635
|
+
.describe('Absolute path to a JSONL file of decision forks on the MCP host filesystem'),
|
|
636
|
+
enableLlmJudge: z
|
|
637
|
+
.boolean()
|
|
638
|
+
.optional()
|
|
639
|
+
.describe('When true and ANTHROPIC_API_KEY is set, refine scores with the pinned LLM judge. Default false uses deterministic rubric only.'),
|
|
640
|
+
});
|
|
641
|
+
const SCORE_DECISIONS_DESCRIPTION = 'Score whether an autonomous agent made the senior-correct call at pivotal decision forks (gate block/pass, stop/continue, escalate/proceed). Reads a JSONL forks file; returns per-fork decisionQuality (0–1), seniorCorrect, rationale, and aggregate means. Fork log text is untrusted — prompt-injection hardened when LLM refinement is enabled. forksPath is traversal-validated within QULIB_FORKS_ALLOWED_ROOT (default: process cwd). Read-only; no writes.';
|
|
642
|
+
async function handleScoreDecisions(input) {
|
|
643
|
+
try {
|
|
644
|
+
const norm = normalize(input.forksPath.trim());
|
|
645
|
+
if (!isAbsolute(norm)) {
|
|
646
|
+
throw new Error('forksPath must be an absolute path on the MCP host');
|
|
647
|
+
}
|
|
648
|
+
log.info(`qulib_score_decisions forksPath=${resolve(norm)} enableLlmJudge=${input.enableLlmJudge ?? false}`);
|
|
649
|
+
const result = await scoreDecisions({
|
|
650
|
+
forksPath: resolve(norm),
|
|
651
|
+
enableLlmJudge: input.enableLlmJudge,
|
|
652
|
+
});
|
|
653
|
+
log.info(`qulib_score_decisions done count=${result.aggregate.count} mean=${result.aggregate.meanDecisionQuality}`);
|
|
654
|
+
return {
|
|
655
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
catch (err) {
|
|
659
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
660
|
+
if (msg.includes('forksPath must') ||
|
|
661
|
+
msg.includes('allowed root') ||
|
|
662
|
+
msg.includes('traversal') ||
|
|
663
|
+
msg.includes('not valid JSON') ||
|
|
664
|
+
msg.includes('exceeds maximum') ||
|
|
665
|
+
msg.includes('does not exist or is not accessible')) {
|
|
666
|
+
// Known user-input errors: return the message only, never a stack trace
|
|
667
|
+
// (a Node stack discloses the server's absolute filesystem paths).
|
|
668
|
+
return toolError('QULIB_INPUT_INVALID', msg, undefined);
|
|
669
|
+
}
|
|
670
|
+
log.error(`qulib_score_decisions failed: ${msg}`);
|
|
671
|
+
return toolError('QULIB_DECISION_SCORE_FAILED', msg, err instanceof Error ? err.stack : undefined);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
mcpServer.registerTool('qulib_score_decisions', {
|
|
675
|
+
description: SCORE_DECISIONS_DESCRIPTION,
|
|
676
|
+
inputSchema: ScoreDecisionsInputSchema,
|
|
677
|
+
}, handleScoreDecisions);
|
|
678
|
+
// No non-prefixed `score_decisions` alias: this is a brand-new tool with no
|
|
679
|
+
// prior integrations to keep compatible, and an unprefixed name is ambiguous
|
|
680
|
+
// and widens the attack surface. The canonical name is qulib_score_decisions.
|
|
681
|
+
async function startMcpServer() {
|
|
682
|
+
const transport = new StdioServerTransport();
|
|
683
|
+
await mcpServer.connect(transport);
|
|
684
|
+
}
|
|
685
|
+
const isDirectExecution = process.argv[1] !== undefined &&
|
|
686
|
+
fileURLToPath(import.meta.url) === resolve(process.argv[1]);
|
|
687
|
+
if (isDirectExecution) {
|
|
688
|
+
await startMcpServer();
|
|
689
|
+
}
|
|
@@ -96,7 +96,7 @@ export declare function summarizeAnalyzeResult(result: AnalyzeResult, includeFul
|
|
|
96
96
|
};
|
|
97
97
|
topGaps: {
|
|
98
98
|
path: string;
|
|
99
|
-
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage" | "untested-api-endpoint";
|
|
99
|
+
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage" | "untested-api-endpoint" | "prompt-leakage";
|
|
100
100
|
severity: "critical" | "high" | "medium" | "low";
|
|
101
101
|
reason: string;
|
|
102
102
|
}[];
|
|
@@ -152,7 +152,7 @@ export declare function summarizeAnalyzeResult(result: AnalyzeResult, includeFul
|
|
|
152
152
|
id: string;
|
|
153
153
|
severity: "critical" | "high" | "medium" | "low";
|
|
154
154
|
reason: string;
|
|
155
|
-
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage" | "untested-api-endpoint";
|
|
155
|
+
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage" | "untested-api-endpoint" | "prompt-leakage";
|
|
156
156
|
recommendation?: string | undefined;
|
|
157
157
|
description?: string | undefined;
|
|
158
158
|
}[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarize-analyze-result.d.ts","sourceRoot":"","sources":["../src/summarize-analyze-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqBjD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"summarize-analyze-result.d.ts","sourceRoot":"","sources":["../src/summarize-analyze-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqBjD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA6Gihe,CAAC;sBAA4C,CAAC;sBAA4C,CAAC;iBAAuC,CAAC;;;;;;;;;;;;;;;;;uBAAghB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;EAD5vf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-error.d.ts","sourceRoot":"","sources":["../src/tool-error.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG;IAC1E,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3C,CASA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qulib/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "MCP server for Qulib — AI-callable release confidence. Seven tools: fused verdict, live-app scan, automation maturity, API coverage, test scaffold, and auth tools.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Tapesh Nagarwal",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"build": "npm --prefix ../.. run build -w @qulib/core && tsc && chmod +x dist/index.js",
|
|
31
31
|
"prepublishOnly": "npm run build",
|
|
32
32
|
"dev": "tsx src/index.ts",
|
|
33
|
-
"test": "node --import tsx/esm --test src/__tests__/summarize-analyze-result.test.ts src/__tests__/analyze-app-mcp-payload.test.ts src/__tests__/score-confidence-mcp.test.ts src/__tests__/naming-aliases.test.ts"
|
|
33
|
+
"test": "node --import tsx/esm --test src/__tests__/summarize-analyze-result.test.ts src/__tests__/analyze-app-mcp-payload.test.ts src/__tests__/score-confidence-mcp.test.ts src/__tests__/naming-aliases.test.ts src/__tests__/diff.test.ts"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
37
|
-
"@qulib/core": "0.
|
|
37
|
+
"@qulib/core": "0.11.0",
|
|
38
38
|
"zod": "^3.23.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|