simple-dynamsoft-mcp 6.2.0 → 6.4.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/.env.example +18 -0
- package/README.md +98 -19
- package/data/metadata/data-manifest.json +140 -0
- package/data/metadata/dynamsoft_sdks.json +203 -3
- package/package.json +11 -2
- package/scripts/prebuild-rag-index.mjs +24 -3
- package/scripts/run-gemini-tests.mjs +25 -0
- package/scripts/update-sdk-versions.mjs +342 -0
- package/scripts/verify-doc-resources.mjs +79 -0
- package/src/gemini-retry.js +148 -0
- package/src/index.js +293 -25
- package/src/normalizers.js +67 -8
- package/src/rag.js +649 -63
- package/src/resource-index/builders.js +294 -0
- package/src/resource-index/config.js +57 -0
- package/src/resource-index/paths.js +15 -0
- package/src/resource-index/samples.js +244 -2
- package/src/resource-index/uri.js +10 -0
- package/src/resource-index/version-policy.js +11 -1
- package/src/resource-index.js +188 -7
package/src/index.js
CHANGED
|
@@ -31,9 +31,15 @@ const {
|
|
|
31
31
|
LATEST_VERSIONS,
|
|
32
32
|
LATEST_MAJOR,
|
|
33
33
|
discoverDwtSamples,
|
|
34
|
+
discoverDcvMobileSamples,
|
|
35
|
+
discoverDcvServerSamples,
|
|
36
|
+
discoverDcvWebSamples,
|
|
34
37
|
findCodeFilesInSample,
|
|
35
38
|
getMobileSamplePath,
|
|
36
39
|
getDbrServerSamplePath,
|
|
40
|
+
getDcvMobileSamplePath,
|
|
41
|
+
getDcvServerSamplePath,
|
|
42
|
+
getDcvWebSamplePath,
|
|
37
43
|
getDwtSamplePath,
|
|
38
44
|
getDdvSamplePath,
|
|
39
45
|
readCodeFile,
|
|
@@ -72,7 +78,7 @@ const {
|
|
|
72
78
|
const server = new McpServer({
|
|
73
79
|
name: "simple-dynamsoft-mcp",
|
|
74
80
|
version: pkg.version,
|
|
75
|
-
description: "MCP server for latest major versions of Dynamsoft SDKs: Barcode Reader
|
|
81
|
+
description: "MCP server for latest major versions of Dynamsoft SDKs: Capture Vision, Barcode Reader, Dynamic Web TWAIN, and Document Viewer. Includes guidance for choosing DBR vs DCV by scenario."
|
|
76
82
|
});
|
|
77
83
|
|
|
78
84
|
function formatScoreLabel(entry) {
|
|
@@ -93,7 +99,7 @@ server.registerTool(
|
|
|
93
99
|
"get_index",
|
|
94
100
|
{
|
|
95
101
|
title: "Get Index",
|
|
96
|
-
description: "Get a compact index of products, editions, versions,
|
|
102
|
+
description: "Get a compact index of products, editions, versions, samples/docs, plus DBR-vs-DCV selection guidance.",
|
|
97
103
|
inputSchema: {}
|
|
98
104
|
},
|
|
99
105
|
async () => ({
|
|
@@ -109,12 +115,12 @@ server.registerTool(
|
|
|
109
115
|
"search",
|
|
110
116
|
{
|
|
111
117
|
title: "Search",
|
|
112
|
-
description: "Semantic (RAG) search across docs and samples with fuzzy fallback; returns resource links for lazy loading.",
|
|
118
|
+
description: "Semantic (RAG) search across docs and samples with fuzzy fallback; returns resource links for lazy loading. Prefer DCV for MRZ/VIN/document-normalization/driver-license scenarios; DBR for barcode-only.",
|
|
113
119
|
inputSchema: {
|
|
114
120
|
query: z.string().describe("Keywords to search across docs and samples."),
|
|
115
|
-
product: z.string().optional().describe("Product: dbr, dwt, ddv"),
|
|
116
|
-
edition: z.string().optional().describe("Edition: mobile, web, server/desktop"),
|
|
117
|
-
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview"),
|
|
121
|
+
product: z.string().optional().describe("Product: dcv, dbr, dwt, ddv"),
|
|
122
|
+
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
123
|
+
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview, spm, core"),
|
|
118
124
|
version: z.string().optional().describe("Version constraint (major or full version)"),
|
|
119
125
|
type: z.enum(["doc", "sample", "index", "policy", "any"]).optional(),
|
|
120
126
|
limit: z.number().int().min(1).max(10).optional().describe("Max results (default 5)")
|
|
@@ -209,11 +215,11 @@ server.registerTool(
|
|
|
209
215
|
"list_samples",
|
|
210
216
|
{
|
|
211
217
|
title: "List Samples",
|
|
212
|
-
description: "List available sample IDs and URIs for a given scope.",
|
|
218
|
+
description: "List available sample IDs and URIs for a given scope. Use DCV scope for MRZ/VIN/document normalization scenarios.",
|
|
213
219
|
inputSchema: {
|
|
214
|
-
product: z.string().optional().describe("Product: dbr, dwt, ddv"),
|
|
215
|
-
edition: z.string().optional().describe("Edition: mobile, web, server/desktop"),
|
|
216
|
-
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview"),
|
|
220
|
+
product: z.string().optional().describe("Product: dcv, dbr, dwt, ddv"),
|
|
221
|
+
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
222
|
+
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview, spm, core"),
|
|
217
223
|
limit: z.number().int().min(1).max(200).optional().describe("Max results (default 50)")
|
|
218
224
|
}
|
|
219
225
|
},
|
|
@@ -291,9 +297,9 @@ server.registerTool(
|
|
|
291
297
|
description: "Resolve a sample_id (or sample URI) to matching sample URIs.",
|
|
292
298
|
inputSchema: {
|
|
293
299
|
sample_id: z.string().describe("Sample identifier or sample:// URI"),
|
|
294
|
-
product: z.string().optional().describe("Product: dbr, dwt, ddv"),
|
|
295
|
-
edition: z.string().optional().describe("Edition: mobile, web, server/desktop"),
|
|
296
|
-
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview"),
|
|
300
|
+
product: z.string().optional().describe("Product: dcv, dbr, dwt, ddv"),
|
|
301
|
+
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
302
|
+
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview, spm, core"),
|
|
297
303
|
limit: z.number().int().min(1).max(10).optional().describe("Max results (default 5)")
|
|
298
304
|
}
|
|
299
305
|
},
|
|
@@ -517,9 +523,9 @@ server.registerTool(
|
|
|
517
523
|
title: "Resolve Version",
|
|
518
524
|
description: "Resolve a concrete latest-major version for a product/edition/platform.",
|
|
519
525
|
inputSchema: {
|
|
520
|
-
product: z.string().describe("Product: dbr, dwt, or ddv"),
|
|
521
|
-
edition: z.string().optional().describe("Edition: mobile, web, server/desktop"),
|
|
522
|
-
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview"),
|
|
526
|
+
product: z.string().describe("Product: dcv, dbr, dwt, or ddv"),
|
|
527
|
+
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
528
|
+
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview, spm, core"),
|
|
523
529
|
constraint: z.string().optional().describe("Version constraint, e.g., latest, 11.x, 10"),
|
|
524
530
|
feature: z.string().optional().describe("Optional feature hint")
|
|
525
531
|
}
|
|
@@ -529,10 +535,10 @@ server.registerTool(
|
|
|
529
535
|
const normalizedPlatform = normalizePlatform(platform);
|
|
530
536
|
const normalizedEdition = normalizeEdition(edition, normalizedPlatform, normalizedProduct);
|
|
531
537
|
|
|
532
|
-
if (!["dbr", "dwt", "ddv"].includes(normalizedProduct)) {
|
|
538
|
+
if (!["dcv", "dbr", "dwt", "ddv"].includes(normalizedProduct)) {
|
|
533
539
|
return {
|
|
534
540
|
isError: true,
|
|
535
|
-
content: [{ type: "text", text: `Unknown product "${product}". Use dbr, dwt, or ddv.` }]
|
|
541
|
+
content: [{ type: "text", text: `Unknown product "${product}". Use dcv, dbr, dwt, or ddv.` }]
|
|
536
542
|
};
|
|
537
543
|
}
|
|
538
544
|
|
|
@@ -548,6 +554,41 @@ server.registerTool(
|
|
|
548
554
|
return { isError: true, content: [{ type: "text", text: policy.message }] };
|
|
549
555
|
}
|
|
550
556
|
|
|
557
|
+
if (normalizedProduct === "dcv") {
|
|
558
|
+
if (!normalizedEdition) {
|
|
559
|
+
const lines = [
|
|
560
|
+
"# DCV Version Resolution",
|
|
561
|
+
`- Latest major: v${LATEST_MAJOR.dcv}`,
|
|
562
|
+
`- Core: ${LATEST_VERSIONS.dcv.core}`,
|
|
563
|
+
`- Web: ${LATEST_VERSIONS.dcv.web}`,
|
|
564
|
+
`- Mobile: ${LATEST_VERSIONS.dcv.mobile}`,
|
|
565
|
+
`- Server/Desktop: ${LATEST_VERSIONS.dcv.server}`,
|
|
566
|
+
"",
|
|
567
|
+
"Specify edition/platform to resolve a single version."
|
|
568
|
+
];
|
|
569
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const resolved = LATEST_VERSIONS.dcv[normalizedEdition];
|
|
573
|
+
if (!resolved) {
|
|
574
|
+
return {
|
|
575
|
+
isError: true,
|
|
576
|
+
content: [{ type: "text", text: `Edition "${normalizedEdition}" is not hosted by this MCP server.` }]
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const displayPlatform = normalizedPlatform === "web" ? "js" : normalizedPlatform;
|
|
581
|
+
const lines = [
|
|
582
|
+
"# DCV Version Resolution",
|
|
583
|
+
`- Edition: ${normalizedEdition}`,
|
|
584
|
+
displayPlatform ? `- Platform: ${displayPlatform}` : "",
|
|
585
|
+
`- Latest major: v${LATEST_MAJOR.dcv}`,
|
|
586
|
+
`- Resolved version: ${resolved}`
|
|
587
|
+
].filter(Boolean);
|
|
588
|
+
|
|
589
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
590
|
+
}
|
|
591
|
+
|
|
551
592
|
if (normalizedProduct === "dbr") {
|
|
552
593
|
if (!normalizedEdition) {
|
|
553
594
|
const lines = [
|
|
@@ -609,15 +650,15 @@ server.registerTool(
|
|
|
609
650
|
"get_quickstart",
|
|
610
651
|
{
|
|
611
652
|
title: "Get Quickstart",
|
|
612
|
-
description: "Opinionated quickstart for a target product/edition/platform.",
|
|
653
|
+
description: "Opinionated quickstart for a target product/edition/platform. DCV supports MRZ/VIN/document-normalization/driver-license workflows.",
|
|
613
654
|
inputSchema: {
|
|
614
|
-
product: z.string().describe("Product: dbr, dwt, or ddv"),
|
|
615
|
-
edition: z.string().optional().describe("Edition: mobile, web, server/desktop"),
|
|
616
|
-
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview"),
|
|
655
|
+
product: z.string().describe("Product: dcv, dbr, dwt, or ddv"),
|
|
656
|
+
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
657
|
+
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview, spm, core"),
|
|
617
658
|
language: z.string().optional().describe("Language hint: kotlin, java, swift, js, ts, python, cpp, csharp, react, vue, angular"),
|
|
618
659
|
version: z.string().optional().describe("Version constraint"),
|
|
619
660
|
api_level: z.string().optional().describe("API level: high-level or low-level (mobile only)"),
|
|
620
|
-
scenario: z.string().optional().describe("Scenario: camera, image, single, multiple, react, etc.")
|
|
661
|
+
scenario: z.string().optional().describe("Scenario: camera, image, single, multiple, MRZ, VIN, document scan/normalization, driver license, react, etc.")
|
|
621
662
|
}
|
|
622
663
|
},
|
|
623
664
|
async ({ product, edition, platform, language, version, api_level, scenario }) => {
|
|
@@ -636,6 +677,212 @@ server.registerTool(
|
|
|
636
677
|
return { isError: true, content: [{ type: "text", text: policy.message }] };
|
|
637
678
|
}
|
|
638
679
|
|
|
680
|
+
if (normalizedProduct === "dcv") {
|
|
681
|
+
const scenarioLower = `${scenario || ""} ${language || ""}`.toLowerCase();
|
|
682
|
+
const effectiveEdition = normalizedEdition || (normalizedPlatform ? normalizeEdition("", normalizedPlatform, "dcv") : "server");
|
|
683
|
+
|
|
684
|
+
function selectDcvServerSample(platformHint, hint) {
|
|
685
|
+
const platformName = normalizePlatform(platformHint) || "python";
|
|
686
|
+
if (platformName === "python") {
|
|
687
|
+
if (hint.includes("mrz")) return "mrz_scanner";
|
|
688
|
+
if (hint.includes("vin")) return "vin_scanner";
|
|
689
|
+
if (hint.includes("driver") || hint.includes("license")) return "driver_license_scanner";
|
|
690
|
+
if (hint.includes("gs1")) return "gs1_ai_scanner";
|
|
691
|
+
return "document_scanner";
|
|
692
|
+
}
|
|
693
|
+
if (platformName === "nodejs") {
|
|
694
|
+
if (hint.includes("lambda")) return "lambda";
|
|
695
|
+
if (hint.includes("pdf")) return "pdf-advanced";
|
|
696
|
+
if (hint.includes("koa")) return "koa";
|
|
697
|
+
return "express";
|
|
698
|
+
}
|
|
699
|
+
if (hint.includes("mrz")) return "MRZScanner";
|
|
700
|
+
if (hint.includes("vin")) return "VINScanner";
|
|
701
|
+
if (hint.includes("driver") || hint.includes("license")) return "DriverLicenseScanner";
|
|
702
|
+
if (hint.includes("gs1")) return "GS1AIScanner";
|
|
703
|
+
return "DocumentScanner";
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
function selectMobileSample(sampleNames, hint) {
|
|
707
|
+
const lowerToName = new Map(sampleNames.map((name) => [String(name).toLowerCase(), name]));
|
|
708
|
+
const candidates = hint.includes("mrz")
|
|
709
|
+
? ["scanmrz", "mrzscanner"]
|
|
710
|
+
: hint.includes("vin")
|
|
711
|
+
? ["scanvin", "vinscanner"]
|
|
712
|
+
: (hint.includes("driver") || hint.includes("license"))
|
|
713
|
+
? ["driverlicensescanner"]
|
|
714
|
+
: ["scandocument", "documentscanner"];
|
|
715
|
+
for (const candidate of candidates) {
|
|
716
|
+
if (lowerToName.has(candidate)) return lowerToName.get(candidate);
|
|
717
|
+
}
|
|
718
|
+
return sampleNames[0] || "";
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function readBestSampleContent(samplePath) {
|
|
722
|
+
if (!samplePath || !existsSync(samplePath)) return { text: "", fence: "text" };
|
|
723
|
+
const sampleStat = statSync(samplePath);
|
|
724
|
+
if (sampleStat.isFile()) {
|
|
725
|
+
return {
|
|
726
|
+
text: readCodeFile(samplePath),
|
|
727
|
+
fence: extname(samplePath).replace(".", "") || "text"
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
const readmePath = join(samplePath, "README.md");
|
|
731
|
+
if (existsSync(readmePath)) return { text: readCodeFile(readmePath), fence: "markdown" };
|
|
732
|
+
|
|
733
|
+
const codeFiles = findCodeFilesInSample(samplePath);
|
|
734
|
+
if (codeFiles.length > 0) {
|
|
735
|
+
const preferredNames = ["index.html", "index.js", "index.ts", "main.dart", "App.tsx", "MainActivity.kt", "MainActivity.java"];
|
|
736
|
+
const preferred = codeFiles.find((file) => preferredNames.includes(file.filename)) || codeFiles[0];
|
|
737
|
+
return {
|
|
738
|
+
text: readCodeFile(preferred.path),
|
|
739
|
+
fence: preferred.extension ? preferred.extension.replace(".", "") : "text"
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
return { text: "Sample found, but no code files detected.", fence: "text" };
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function formatInstallLines(installation) {
|
|
747
|
+
if (!installation || typeof installation !== "object") return [];
|
|
748
|
+
const lines = [];
|
|
749
|
+
for (const value of Object.values(installation)) {
|
|
750
|
+
if (typeof value === "string" && value.trim()) lines.push(value);
|
|
751
|
+
}
|
|
752
|
+
return lines;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
if (effectiveEdition === "server") {
|
|
756
|
+
const sdkEntry = registry.sdks["dcv-server"];
|
|
757
|
+
const targetPlatform = normalizePlatform(normalizedPlatform || sdkEntry.default_platform || "python");
|
|
758
|
+
const sampleName = selectDcvServerSample(targetPlatform, scenarioLower);
|
|
759
|
+
const samplePath = getDcvServerSamplePath(targetPlatform, sampleName);
|
|
760
|
+
|
|
761
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
762
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const { text: sampleContent, fence } = readBestSampleContent(samplePath);
|
|
766
|
+
const installLines = formatInstallLines(sdkEntry.platforms?.[targetPlatform]?.installation);
|
|
767
|
+
|
|
768
|
+
return {
|
|
769
|
+
content: [{
|
|
770
|
+
type: "text",
|
|
771
|
+
text: [
|
|
772
|
+
`# Quick Start: DCV Server (${targetPlatform})`,
|
|
773
|
+
"",
|
|
774
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
775
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
776
|
+
"",
|
|
777
|
+
installLines.length ? "## Install" : "",
|
|
778
|
+
installLines.length ? "```bash" : "",
|
|
779
|
+
...installLines,
|
|
780
|
+
installLines.length ? "```" : "",
|
|
781
|
+
installLines.length ? "" : "",
|
|
782
|
+
`## ${sampleName}`,
|
|
783
|
+
"```" + fence,
|
|
784
|
+
sampleContent,
|
|
785
|
+
"```",
|
|
786
|
+
"",
|
|
787
|
+
`Docs: ${sdkEntry.platforms?.[targetPlatform]?.docs?.["user-guide"] || "N/A"}`
|
|
788
|
+
].filter(Boolean).join("\n")
|
|
789
|
+
}]
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (effectiveEdition === "web") {
|
|
794
|
+
const sdkEntry = registry.sdks["dcv-web"];
|
|
795
|
+
const available = discoverDcvWebSamples();
|
|
796
|
+
const sampleName = scenarioLower.includes("vin") ? "VINScanner" : (available[0] || "VINScanner");
|
|
797
|
+
const samplePath = getDcvWebSamplePath(sampleName);
|
|
798
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
799
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
800
|
+
}
|
|
801
|
+
const { text: sampleContent, fence } = readBestSampleContent(samplePath);
|
|
802
|
+
const installLines = formatInstallLines(sdkEntry.platforms?.web?.installation);
|
|
803
|
+
|
|
804
|
+
return {
|
|
805
|
+
content: [{
|
|
806
|
+
type: "text",
|
|
807
|
+
text: [
|
|
808
|
+
"# Quick Start: DCV Web",
|
|
809
|
+
"",
|
|
810
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
811
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
812
|
+
"",
|
|
813
|
+
installLines.length ? "## Install" : "",
|
|
814
|
+
installLines.length ? "```bash" : "",
|
|
815
|
+
...installLines,
|
|
816
|
+
installLines.length ? "```" : "",
|
|
817
|
+
installLines.length ? "" : "",
|
|
818
|
+
`## ${sampleName}`,
|
|
819
|
+
"```" + fence,
|
|
820
|
+
sampleContent,
|
|
821
|
+
"```",
|
|
822
|
+
"",
|
|
823
|
+
`Docs: ${sdkEntry.platforms?.web?.docs?.["user-guide"] || "N/A"}`
|
|
824
|
+
].filter(Boolean).join("\n")
|
|
825
|
+
}]
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (effectiveEdition === "mobile") {
|
|
830
|
+
const sdkEntry = registry.sdks["dcv-mobile"];
|
|
831
|
+
const targetPlatform = normalizePlatform(normalizedPlatform || sdkEntry.default_platform || "android");
|
|
832
|
+
const sampleNames = discoverDcvMobileSamples(targetPlatform);
|
|
833
|
+
const sampleName = selectMobileSample(sampleNames, scenarioLower);
|
|
834
|
+
const samplePath = getDcvMobileSamplePath(targetPlatform, sampleName);
|
|
835
|
+
|
|
836
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
837
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName || "N/A"}.` }] };
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
const { text: sampleContent, fence } = readBestSampleContent(samplePath);
|
|
841
|
+
const installLines = formatInstallLines(sdkEntry.platforms?.[targetPlatform]?.installation);
|
|
842
|
+
|
|
843
|
+
return {
|
|
844
|
+
content: [{
|
|
845
|
+
type: "text",
|
|
846
|
+
text: [
|
|
847
|
+
`# Quick Start: DCV Mobile (${targetPlatform})`,
|
|
848
|
+
"",
|
|
849
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
850
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
851
|
+
"",
|
|
852
|
+
installLines.length ? "## Install" : "",
|
|
853
|
+
installLines.length ? "```bash" : "",
|
|
854
|
+
...installLines,
|
|
855
|
+
installLines.length ? "```" : "",
|
|
856
|
+
installLines.length ? "" : "",
|
|
857
|
+
`## ${sampleName}`,
|
|
858
|
+
"```" + fence,
|
|
859
|
+
sampleContent,
|
|
860
|
+
"```",
|
|
861
|
+
"",
|
|
862
|
+
`Docs: ${sdkEntry.platforms?.[targetPlatform]?.docs?.["user-guide"] || "N/A"}`
|
|
863
|
+
].filter(Boolean).join("\n")
|
|
864
|
+
}]
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
if (effectiveEdition === "core") {
|
|
869
|
+
const sdkEntry = registry.sdks["dcv-core"];
|
|
870
|
+
return {
|
|
871
|
+
content: [{
|
|
872
|
+
type: "text",
|
|
873
|
+
text: [
|
|
874
|
+
"# Quick Start: DCV Core",
|
|
875
|
+
"",
|
|
876
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
877
|
+
"",
|
|
878
|
+
"DCV core docs aggregate architecture, parameters, and cross-product workflows.",
|
|
879
|
+
`Docs: ${sdkEntry.platforms?.core?.docs?.introduction || "https://www.dynamsoft.com/capture-vision/docs/core/"}`
|
|
880
|
+
].join("\n")
|
|
881
|
+
}]
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
|
|
639
886
|
if (normalizedProduct === "dbr" && normalizedEdition === "server") {
|
|
640
887
|
const sdkEntry = registry.sdks["dbr-server"];
|
|
641
888
|
const scenarioLower = (scenario || "").toLowerCase();
|
|
@@ -946,7 +1193,7 @@ server.registerTool(
|
|
|
946
1193
|
title: "Generate Project",
|
|
947
1194
|
description: "Generate a project structure from a sample and return files inline (no zip/download).",
|
|
948
1195
|
inputSchema: {
|
|
949
|
-
product: z.string().describe("Product: dbr, dwt, or ddv"),
|
|
1196
|
+
product: z.string().describe("Product: dcv, dbr, dwt, or ddv"),
|
|
950
1197
|
edition: z.string().optional().describe("Edition: mobile, web, server/desktop"),
|
|
951
1198
|
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview"),
|
|
952
1199
|
version: z.string().optional().describe("Version constraint"),
|
|
@@ -1018,6 +1265,12 @@ server.registerTool(
|
|
|
1018
1265
|
samplePath = getWebSamplePath(sampleInfo.category, sampleInfo.sampleName);
|
|
1019
1266
|
} else if (sampleInfo.product === "dbr" && (sampleInfo.edition === "python" || sampleInfo.edition === "server")) {
|
|
1020
1267
|
samplePath = getDbrServerSamplePath(sampleInfo.platform, sampleInfo.sampleName);
|
|
1268
|
+
} else if (sampleInfo.product === "dcv" && sampleInfo.edition === "mobile") {
|
|
1269
|
+
samplePath = getDcvMobileSamplePath(sampleInfo.platform, sampleInfo.sampleName);
|
|
1270
|
+
} else if (sampleInfo.product === "dcv" && sampleInfo.edition === "server") {
|
|
1271
|
+
samplePath = getDcvServerSamplePath(sampleInfo.platform, sampleInfo.sampleName);
|
|
1272
|
+
} else if (sampleInfo.product === "dcv" && sampleInfo.edition === "web") {
|
|
1273
|
+
samplePath = getDcvWebSamplePath(sampleInfo.sampleName);
|
|
1021
1274
|
} else if (sampleInfo.product === "dwt") {
|
|
1022
1275
|
samplePath = getDwtSamplePath(sampleInfo.category, sampleInfo.sampleName);
|
|
1023
1276
|
} else if (sampleInfo.product === "ddv") {
|
|
@@ -1045,6 +1298,21 @@ server.registerTool(
|
|
|
1045
1298
|
const altLevel = level === "high-level" ? "low-level" : "high-level";
|
|
1046
1299
|
const alternatePath = getMobileSamplePath(targetPlatform, altLevel, sampleName);
|
|
1047
1300
|
samplePath = existsSync(primaryPath) ? primaryPath : (existsSync(alternatePath) ? alternatePath : null);
|
|
1301
|
+
} else if (normalizedProduct === "dcv" && normalizedEdition === "mobile") {
|
|
1302
|
+
const platformCandidates = normalizedPlatform
|
|
1303
|
+
? [normalizedPlatform]
|
|
1304
|
+
: ["android", "ios", "react-native", "flutter", "maui", "spm"];
|
|
1305
|
+
for (const platformCandidate of platformCandidates) {
|
|
1306
|
+
const candidate = getDcvMobileSamplePath(platformCandidate, sampleName);
|
|
1307
|
+
if (candidate && existsSync(candidate)) {
|
|
1308
|
+
samplePath = candidate;
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
} else if (normalizedProduct === "dcv" && normalizedEdition === "web") {
|
|
1313
|
+
samplePath = getDcvWebSamplePath(sampleName);
|
|
1314
|
+
} else if (normalizedProduct === "dcv" && normalizedEdition === "server") {
|
|
1315
|
+
samplePath = getDcvServerSamplePath(normalizedPlatform || "python", sampleName);
|
|
1048
1316
|
} else if (normalizedProduct === "dbr" && normalizedEdition === "web") {
|
|
1049
1317
|
samplePath = getWebSamplePath(undefined, sampleName);
|
|
1050
1318
|
} else if (normalizedProduct === "dbr" && normalizedEdition === "server") {
|
|
@@ -1212,7 +1480,7 @@ server.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
|
1212
1480
|
|
|
1213
1481
|
server.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
1214
1482
|
const parsed = parseResourceUri(request.params.uri);
|
|
1215
|
-
if (parsed && ["dbr", "dwt", "ddv"].includes(parsed.product)) {
|
|
1483
|
+
if (parsed && ["dcv", "dbr", "dwt", "ddv"].includes(parsed.product)) {
|
|
1216
1484
|
const policy = ensureLatestMajor({
|
|
1217
1485
|
product: parsed.product,
|
|
1218
1486
|
version: parsed.version,
|
package/src/normalizers.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
const sdkAliases = {
|
|
2
|
+
// DCV
|
|
3
|
+
"dcv": "dcv-mobile",
|
|
4
|
+
"dcv-mobile": "dcv-mobile",
|
|
5
|
+
"dcv-server": "dcv-server",
|
|
6
|
+
"dcv-web": "dcv-web",
|
|
7
|
+
"capture vision": "dcv-mobile",
|
|
8
|
+
"capture-vision": "dcv-mobile",
|
|
9
|
+
"dynamsoft capture vision": "dcv-mobile",
|
|
10
|
+
"mrz scanner": "dcv-mobile",
|
|
11
|
+
"vin scanner": "dcv-mobile",
|
|
12
|
+
"driver license scanner": "dcv-mobile",
|
|
13
|
+
"document normalization": "dcv-mobile",
|
|
14
|
+
"document normalizer": "dcv-mobile",
|
|
2
15
|
// DDV
|
|
3
16
|
"ddv": "ddv",
|
|
4
17
|
"document-viewer": "ddv",
|
|
@@ -31,10 +44,7 @@ const sdkAliases = {
|
|
|
31
44
|
"web twain": "dwt",
|
|
32
45
|
"webtwain": "dwt",
|
|
33
46
|
"dynamic web twain": "dwt",
|
|
34
|
-
"
|
|
35
|
-
"document scanning": "dwt",
|
|
36
|
-
"twain": "dwt",
|
|
37
|
-
"scanner": "dwt"
|
|
47
|
+
"twain": "dwt"
|
|
38
48
|
};
|
|
39
49
|
|
|
40
50
|
const platformAliases = {
|
|
@@ -54,6 +64,9 @@ const platformAliases = {
|
|
|
54
64
|
maui: "maui",
|
|
55
65
|
"dotnet maui": "maui",
|
|
56
66
|
".net maui": "maui",
|
|
67
|
+
spm: "spm",
|
|
68
|
+
"swift package manager": "spm",
|
|
69
|
+
"swiftpm": "spm",
|
|
57
70
|
// Desktop/Server
|
|
58
71
|
python: "python",
|
|
59
72
|
py: "python",
|
|
@@ -147,6 +160,29 @@ const sampleAliases = {
|
|
|
147
160
|
"upload": "upload"
|
|
148
161
|
};
|
|
149
162
|
|
|
163
|
+
const dcvFeatureTerms = [
|
|
164
|
+
"capture vision",
|
|
165
|
+
"mrz",
|
|
166
|
+
"machine readable zone",
|
|
167
|
+
"vin",
|
|
168
|
+
"vehicle identification",
|
|
169
|
+
"driver license",
|
|
170
|
+
"drivers license",
|
|
171
|
+
"id card",
|
|
172
|
+
"passport",
|
|
173
|
+
"document normalization",
|
|
174
|
+
"document normalizer",
|
|
175
|
+
"document scanner",
|
|
176
|
+
"document scanning",
|
|
177
|
+
"document scan",
|
|
178
|
+
"auto capture",
|
|
179
|
+
"auto-capture",
|
|
180
|
+
"cropping",
|
|
181
|
+
"crop"
|
|
182
|
+
];
|
|
183
|
+
|
|
184
|
+
const dwtFeatureTerms = ["dwt", "web twain", "webtwain", "twain", "wia", "ica", "sane"];
|
|
185
|
+
|
|
150
186
|
let webFrameworkPlatformsGetter = null;
|
|
151
187
|
|
|
152
188
|
function getWebFrameworkPlatformsInternal() {
|
|
@@ -198,6 +234,23 @@ function normalizeSampleName(name) {
|
|
|
198
234
|
function normalizeProduct(product) {
|
|
199
235
|
if (!product) return "";
|
|
200
236
|
const normalized = product.trim().toLowerCase();
|
|
237
|
+
if (
|
|
238
|
+
[
|
|
239
|
+
"dcv",
|
|
240
|
+
"capture vision",
|
|
241
|
+
"capture-vision",
|
|
242
|
+
"dynamsoft capture vision",
|
|
243
|
+
"dynamsoft capture vision sdk",
|
|
244
|
+
"capture vision bundle",
|
|
245
|
+
"mrz scanner",
|
|
246
|
+
"vin scanner",
|
|
247
|
+
"driver license scanner",
|
|
248
|
+
"document scanner",
|
|
249
|
+
"document normalization"
|
|
250
|
+
].includes(normalized)
|
|
251
|
+
) {
|
|
252
|
+
return "dcv";
|
|
253
|
+
}
|
|
201
254
|
if (["ddv", "document viewer", "document-viewer", "dynamsoft document viewer", "doc viewer", "pdf viewer"].includes(normalized)) {
|
|
202
255
|
return "ddv";
|
|
203
256
|
}
|
|
@@ -215,7 +268,8 @@ function normalizeEdition(edition, platform, product) {
|
|
|
215
268
|
const normalizedPlatform = normalizePlatform(platform);
|
|
216
269
|
|
|
217
270
|
if (!edition) {
|
|
218
|
-
if (
|
|
271
|
+
if (product === "dcv" && normalizedPlatform === "core") return "core";
|
|
272
|
+
if (["android", "ios", "maui", "react-native", "flutter", "spm"].includes(normalizedPlatform)) return "mobile";
|
|
219
273
|
if (isWebPlatform(normalizedPlatform)) return "web";
|
|
220
274
|
if (isServerPlatform(normalizedPlatform)) return "server";
|
|
221
275
|
return "";
|
|
@@ -223,8 +277,9 @@ function normalizeEdition(edition, platform, product) {
|
|
|
223
277
|
|
|
224
278
|
const normalized = edition.trim().toLowerCase();
|
|
225
279
|
const compact = normalized.replace(/\s+/g, "");
|
|
226
|
-
if (["mobile", "android", "ios", "maui", "react-native", "react native", "flutter"].includes(normalized)) return "mobile";
|
|
280
|
+
if (["mobile", "android", "ios", "maui", "react-native", "react native", "flutter", "spm"].includes(normalized)) return "mobile";
|
|
227
281
|
if (["web", "javascript", "js", "typescript", "ts"].includes(normalized)) return "web";
|
|
282
|
+
if (normalized === "core") return "core";
|
|
228
283
|
if (["server", "desktop", "server/desktop", "server-desktop", "serverdesktop"].includes(normalized) || compact === "serverdesktop") return "server";
|
|
229
284
|
if (["python", "py", "java", "c++", "cpp", "dotnet", ".net", "c#", "csharp", "node", "nodejs", "node.js"].includes(normalized)) return "server";
|
|
230
285
|
return normalized;
|
|
@@ -245,11 +300,15 @@ function isWebPlatform(platform) {
|
|
|
245
300
|
function inferProductFromQuery(query) {
|
|
246
301
|
if (!query) return "";
|
|
247
302
|
const normalized = query.toLowerCase();
|
|
303
|
+
const isDwtQuery = dwtFeatureTerms.some((term) => normalized.includes(term));
|
|
304
|
+
if (isDwtQuery) return "dwt";
|
|
305
|
+
const isDcvQuery = dcvFeatureTerms.some((term) => normalized.includes(term));
|
|
306
|
+
if (isDcvQuery) return "dcv";
|
|
248
307
|
if (normalized.includes("ddv") || normalized.includes("document viewer") || normalized.includes("pdf viewer") || normalized.includes("edit viewer")) {
|
|
249
308
|
return "ddv";
|
|
250
309
|
}
|
|
251
|
-
if (normalized.includes("
|
|
252
|
-
return "
|
|
310
|
+
if (normalized.includes("dcv") || normalized.includes("capture vision") || normalized.includes("capture-vision")) {
|
|
311
|
+
return "dcv";
|
|
253
312
|
}
|
|
254
313
|
if (normalized.includes("dbr") || normalized.includes("barcode reader") || normalized.includes("barcode")) {
|
|
255
314
|
return "dbr";
|