simple-dynamsoft-mcp 7.2.8 → 7.3.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 +3 -2
- package/data/metadata/data-manifest.json +48 -8
- package/data/metadata/dynamsoft_sdks.json +3 -3
- package/package.json +1 -1
- package/src/data/repo-map.js +42 -2
- package/src/server/create-server.js +6 -1
- package/src/server/normalizers.js +8 -14
- package/src/server/public-offerings.js +71 -0
- package/src/server/resource-index/builders.js +384 -20
- package/src/server/resource-index/config.js +14 -0
- package/src/server/resource-index/paths.js +4 -0
- package/src/server/resource-index/samples.js +148 -1
- package/src/server/resource-index/uri.js +12 -0
- package/src/server/resource-index/version-policy.js +13 -5
- package/src/server/resource-index.js +60 -2
- package/src/server/resources/register-resources.js +1 -1
- package/src/server/tools/public-routing.js +75 -0
- package/src/server/tools/register-index-tools.js +33 -14
- package/src/server/tools/register-project-tools.js +100 -27
- package/src/server/tools/register-quickstart-tools.js +103 -14
- package/src/server/tools/register-sample-tools.js +12 -3
- package/src/server/tools/register-version-tools.js +51 -43
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { dirname, join, relative } from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import { buildUnknownPublicProductResponse, isKnownPublicOffering } from "../public-offerings.js";
|
|
5
|
+
import { buildUnsupportedPublicScopeResponse } from "./public-routing.js";
|
|
4
6
|
|
|
5
7
|
export function registerProjectTools({
|
|
6
8
|
server,
|
|
@@ -22,10 +24,46 @@ export function registerProjectTools({
|
|
|
22
24
|
getDcvMobileSamplePath,
|
|
23
25
|
getDcvServerSamplePath,
|
|
24
26
|
getDcvWebSamplePath,
|
|
27
|
+
getMrzWebSamplePath,
|
|
28
|
+
getMdsWebSamplePath,
|
|
25
29
|
getDwtSamplePath,
|
|
26
30
|
getDdvSamplePath,
|
|
27
31
|
getSampleSuggestions
|
|
28
32
|
}) {
|
|
33
|
+
async function resolveDedicatedPublicWebSamplePath({
|
|
34
|
+
product,
|
|
35
|
+
platform,
|
|
36
|
+
sampleName,
|
|
37
|
+
getSamplePath,
|
|
38
|
+
getSuggestions
|
|
39
|
+
}) {
|
|
40
|
+
const directPath = getSamplePath(undefined, sampleName);
|
|
41
|
+
if (directPath && existsSync(directPath)) {
|
|
42
|
+
return directPath;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const suggestions = await getSuggestions({
|
|
46
|
+
query: sampleName,
|
|
47
|
+
product,
|
|
48
|
+
edition: "web",
|
|
49
|
+
platform,
|
|
50
|
+
limit: 10
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const matchingEntry = suggestions.find((entry) => {
|
|
54
|
+
if (entry.type !== "sample") return false;
|
|
55
|
+
const parsed = parseSampleUri(entry.uri);
|
|
56
|
+
return parsed?.product === product && parsed?.edition === "web" && parsed?.sampleName === sampleName;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (!matchingEntry) {
|
|
60
|
+
return directPath;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const parsed = parseSampleUri(matchingEntry.uri);
|
|
64
|
+
return getSamplePath(parsed?.category, sampleName);
|
|
65
|
+
}
|
|
66
|
+
|
|
29
67
|
server.registerTool(
|
|
30
68
|
"get_sample_files",
|
|
31
69
|
{
|
|
@@ -43,12 +81,12 @@ export function registerProjectTools({
|
|
|
43
81
|
"- If the user just wants a quick code snippet, use get_quickstart instead.",
|
|
44
82
|
"",
|
|
45
83
|
"PARAMETERS:",
|
|
46
|
-
"- product (required):
|
|
84
|
+
"- product (required): dbr, dwt, ddv, mrz, or mds.",
|
|
47
85
|
"- edition: mobile, web, or server.",
|
|
48
86
|
"- platform: android, ios, js, python, cpp, java, dotnet, nodejs, react, vue, angular, flutter, react-native, maui, etc.",
|
|
49
87
|
"- version: Version constraint. Latest major is used by default.",
|
|
50
88
|
"- sample_id: Sample identifier as returned by list_samples (e.g. 'hello-world', 'ScanSingleBarcode'). Requires product/edition.",
|
|
51
|
-
"- resource_uri: A sample:// URI as returned by search (e.g. 'sample://dbr/mobile/android/10/high-level/ScanSingleBarcode'). Preferred over sample_id when available.",
|
|
89
|
+
"- resource_uri: A sample:// URI as returned by search (e.g. 'sample://dbr/mobile/android/10/high-level/ScanSingleBarcode' or 'sample://mrz/server/python/3/mrz_scanner'). Preferred over sample_id when available.",
|
|
52
90
|
"- api_level: 'high-level' or 'low-level' (DBR mobile only).",
|
|
53
91
|
"",
|
|
54
92
|
"RETURNS: A text block containing all project files inline, each under a heading with its relative path and wrapped in a fenced code block. Files larger than 50KB are excluded. No zip file is created.",
|
|
@@ -58,7 +96,7 @@ export function registerProjectTools({
|
|
|
58
96
|
"RELATED TOOLS: list_samples (discover sample IDs), search (find samples by keyword), get_quickstart (quick single-file snippet)."
|
|
59
97
|
].join("\n"),
|
|
60
98
|
inputSchema: {
|
|
61
|
-
product: z.string().trim().min(1, "Product is required.").describe("Product:
|
|
99
|
+
product: z.string().trim().min(1, "Product is required.").describe("Product: dbr, dwt, ddv, mrz, mds"),
|
|
62
100
|
edition: z.string().optional().describe("Edition: mobile, web, server/desktop"),
|
|
63
101
|
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"),
|
|
64
102
|
version: z.string().optional().describe("Version constraint"),
|
|
@@ -74,29 +112,6 @@ export function registerProjectTools({
|
|
|
74
112
|
}
|
|
75
113
|
},
|
|
76
114
|
async ({ product, edition, platform, version, sample_id, resource_uri, api_level }) => {
|
|
77
|
-
const normalizedProduct = normalizeProduct(product);
|
|
78
|
-
const normalizedPlatform = normalizePlatform(platform);
|
|
79
|
-
const normalizedEdition = normalizeEdition(edition, normalizedPlatform, normalizedProduct);
|
|
80
|
-
|
|
81
|
-
await ensureScopeHydrated({
|
|
82
|
-
product: normalizedProduct,
|
|
83
|
-
edition: normalizedEdition,
|
|
84
|
-
platform: normalizedPlatform,
|
|
85
|
-
type: "sample"
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const policy = ensureLatestMajor({
|
|
89
|
-
product: normalizedProduct,
|
|
90
|
-
version,
|
|
91
|
-
query: sample_id,
|
|
92
|
-
edition: normalizedEdition,
|
|
93
|
-
platform: normalizedPlatform
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
if (!policy.ok) {
|
|
97
|
-
return { isError: true, content: [{ type: "text", text: policy.message }] };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
115
|
let sampleInfo = null;
|
|
101
116
|
if (resource_uri) {
|
|
102
117
|
const parsed = parseResourceUri(resource_uri);
|
|
@@ -130,6 +145,35 @@ export function registerProjectTools({
|
|
|
130
145
|
}
|
|
131
146
|
}
|
|
132
147
|
|
|
148
|
+
const normalizedProduct = normalizeProduct(sampleInfo?.product || product);
|
|
149
|
+
if ((sampleInfo?.product || product) && !isKnownPublicOffering(normalizedProduct)) {
|
|
150
|
+
return buildUnknownPublicProductResponse(sampleInfo?.product || product);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const normalizedPlatform = normalizePlatform(sampleInfo?.platform || platform);
|
|
154
|
+
const normalizedEdition = normalizeEdition(sampleInfo?.edition || edition, normalizedPlatform, normalizedProduct);
|
|
155
|
+
const unsupportedScopeResponse = buildUnsupportedPublicScopeResponse(normalizedProduct, normalizedEdition, normalizedPlatform);
|
|
156
|
+
if (unsupportedScopeResponse) return unsupportedScopeResponse;
|
|
157
|
+
|
|
158
|
+
await ensureScopeHydrated({
|
|
159
|
+
product: normalizedProduct,
|
|
160
|
+
edition: normalizedEdition,
|
|
161
|
+
platform: normalizedPlatform,
|
|
162
|
+
type: "sample"
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const policy = ensureLatestMajor({
|
|
166
|
+
product: normalizedProduct,
|
|
167
|
+
version,
|
|
168
|
+
query: sample_id,
|
|
169
|
+
edition: normalizedEdition,
|
|
170
|
+
platform: normalizedPlatform
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (!policy.ok) {
|
|
174
|
+
return { isError: true, content: [{ type: "text", text: policy.message }] };
|
|
175
|
+
}
|
|
176
|
+
|
|
133
177
|
let samplePath = null;
|
|
134
178
|
let sampleLabel = "";
|
|
135
179
|
let sampleQuery = "";
|
|
@@ -143,6 +187,14 @@ export function registerProjectTools({
|
|
|
143
187
|
samplePath = getWebSamplePath(sampleInfo.category, sampleInfo.sampleName);
|
|
144
188
|
} else if (sampleInfo.product === "dbr" && (sampleInfo.edition === "python" || sampleInfo.edition === "server")) {
|
|
145
189
|
samplePath = getDbrServerSamplePath(sampleInfo.platform, sampleInfo.sampleName);
|
|
190
|
+
} else if ((sampleInfo.product === "mrz" || sampleInfo.product === "mds") && sampleInfo.edition === "mobile") {
|
|
191
|
+
samplePath = getDcvMobileSamplePath(sampleInfo.platform, sampleInfo.sampleName);
|
|
192
|
+
} else if ((sampleInfo.product === "mrz" || sampleInfo.product === "mds") && sampleInfo.edition === "server") {
|
|
193
|
+
samplePath = getDcvServerSamplePath(sampleInfo.platform, sampleInfo.sampleName);
|
|
194
|
+
} else if ((sampleInfo.product === "mrz" || sampleInfo.product === "mds") && sampleInfo.edition === "web") {
|
|
195
|
+
samplePath = sampleInfo.product === "mrz"
|
|
196
|
+
? getMrzWebSamplePath(sampleInfo.category, sampleInfo.sampleName)
|
|
197
|
+
: getMdsWebSamplePath(sampleInfo.category, sampleInfo.sampleName);
|
|
146
198
|
} else if (sampleInfo.product === "dcv" && sampleInfo.edition === "mobile") {
|
|
147
199
|
samplePath = getDcvMobileSamplePath(sampleInfo.platform, sampleInfo.sampleName);
|
|
148
200
|
} else if (sampleInfo.product === "dcv" && sampleInfo.edition === "server") {
|
|
@@ -176,6 +228,27 @@ export function registerProjectTools({
|
|
|
176
228
|
const altLevel = level === "high-level" ? "low-level" : "high-level";
|
|
177
229
|
const alternatePath = getMobileSamplePath(targetPlatform, altLevel, sampleName);
|
|
178
230
|
samplePath = existsSync(primaryPath) ? primaryPath : (existsSync(alternatePath) ? alternatePath : null);
|
|
231
|
+
} else if ((normalizedProduct === "mrz" || normalizedProduct === "mds") && normalizedEdition === "mobile") {
|
|
232
|
+
const platformCandidates = normalizedPlatform
|
|
233
|
+
? [normalizedPlatform]
|
|
234
|
+
: ["android", "ios", "react-native", "flutter", "maui", "spm"];
|
|
235
|
+
for (const platformCandidate of platformCandidates) {
|
|
236
|
+
const candidate = getDcvMobileSamplePath(platformCandidate, sampleName);
|
|
237
|
+
if (candidate && existsSync(candidate)) {
|
|
238
|
+
samplePath = candidate;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
} else if ((normalizedProduct === "mrz" || normalizedProduct === "mds") && normalizedEdition === "web") {
|
|
243
|
+
samplePath = await resolveDedicatedPublicWebSamplePath({
|
|
244
|
+
product: normalizedProduct,
|
|
245
|
+
platform: normalizedPlatform,
|
|
246
|
+
sampleName,
|
|
247
|
+
getSamplePath: normalizedProduct === "mrz" ? getMrzWebSamplePath : getMdsWebSamplePath,
|
|
248
|
+
getSuggestions: getSampleSuggestions
|
|
249
|
+
});
|
|
250
|
+
} else if ((normalizedProduct === "mrz" || normalizedProduct === "mds") && normalizedEdition === "server") {
|
|
251
|
+
samplePath = getDcvServerSamplePath(normalizedPlatform || "python", sampleName);
|
|
179
252
|
} else if (normalizedProduct === "dcv" && normalizedEdition === "mobile") {
|
|
180
253
|
const platformCandidates = normalizedPlatform
|
|
181
254
|
? [normalizedPlatform]
|
|
@@ -265,7 +338,7 @@ export function registerProjectTools({
|
|
|
265
338
|
const textExtensions = [
|
|
266
339
|
".java", ".kt", ".swift", ".m", ".h", ".xml", ".gradle", ".properties",
|
|
267
340
|
".pro", ".json", ".plist", ".storyboard", ".xib", ".gitignore", ".md",
|
|
268
|
-
".js", ".jsx", ".ts", ".tsx", ".vue", ".cjs", ".html", ".css"
|
|
341
|
+
".js", ".jsx", ".ts", ".tsx", ".vue", ".cjs", ".html", ".css", ".py"
|
|
269
342
|
];
|
|
270
343
|
|
|
271
344
|
const files = [];
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { existsSync, statSync } from "node:fs";
|
|
2
2
|
import { extname, join } from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import { buildUnknownPublicProductResponse, isKnownPublicOffering } from "../public-offerings.js";
|
|
5
|
+
import { buildUnsupportedPublicScopeResponse } from "./public-routing.js";
|
|
4
6
|
|
|
5
7
|
export function registerQuickstartTools({
|
|
6
8
|
server,
|
|
@@ -25,6 +27,54 @@ export function registerQuickstartTools({
|
|
|
25
27
|
getMainCodeFile,
|
|
26
28
|
getWebSamplePath
|
|
27
29
|
}) {
|
|
30
|
+
function getPublicWebQuickstartLinks(product) {
|
|
31
|
+
if (product === "mrz") {
|
|
32
|
+
return {
|
|
33
|
+
docsUrl: "https://www.dynamsoft.com/mrz-scanner/docs/web/",
|
|
34
|
+
samplesUrl: "https://github.com/Dynamsoft/mrz-scanner-javascript"
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (product === "mds") {
|
|
39
|
+
return {
|
|
40
|
+
docsUrl: "https://www.dynamsoft.com/mobile-document-scanner/docs/web/",
|
|
41
|
+
samplesUrl: "https://github.com/Dynamsoft/document-scanner-javascript"
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { docsUrl: "", samplesUrl: "" };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getPublicProductLabel(product) {
|
|
49
|
+
if (product === "mrz") return "MRZ";
|
|
50
|
+
if (product === "mds") return "MDS";
|
|
51
|
+
if (product === "dbr") return "DBR";
|
|
52
|
+
if (product === "dwt") return "DWT";
|
|
53
|
+
if (product === "ddv") return "DDV";
|
|
54
|
+
return String(product || "").toUpperCase();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function buildPublicReferenceQuickstart({ product, edition, platform, docsUrl, samplesUrl }) {
|
|
58
|
+
const label = getPublicProductLabel(product);
|
|
59
|
+
const scopeParts = [];
|
|
60
|
+
for (const part of [edition, platform]) {
|
|
61
|
+
if (!part || scopeParts.includes(part)) continue;
|
|
62
|
+
scopeParts.push(part);
|
|
63
|
+
}
|
|
64
|
+
const scope = scopeParts.join(" / ") || "general";
|
|
65
|
+
const lines = [
|
|
66
|
+
`# Quick Start Redirect: ${label}`,
|
|
67
|
+
"",
|
|
68
|
+
`${label} is available as a public offering, but this ${scope} quickstart is currently served as reference links instead of an inline starter.`,
|
|
69
|
+
"",
|
|
70
|
+
"Reference links:",
|
|
71
|
+
docsUrl ? `- Docs: ${docsUrl}` : "",
|
|
72
|
+
samplesUrl ? `- Samples: ${samplesUrl}` : ""
|
|
73
|
+
].filter(Boolean);
|
|
74
|
+
|
|
75
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
76
|
+
}
|
|
77
|
+
|
|
28
78
|
server.registerTool(
|
|
29
79
|
"get_quickstart",
|
|
30
80
|
{
|
|
@@ -35,7 +85,7 @@ export function registerQuickstartTools({
|
|
|
35
85
|
"WHEN TO USE:",
|
|
36
86
|
"- When the user wants to get started quickly with a Dynamsoft SDK.",
|
|
37
87
|
"- To generate a ready-to-run code snippet with install commands, license key, and SDK version.",
|
|
38
|
-
"- For scenario-specific starters: pass scenario='MRZ' for passport reading, '
|
|
88
|
+
"- For scenario-specific starters: pass scenario='MRZ' for passport reading, 'document scan' for document normalization, or barcode/image hints for DBR.",
|
|
39
89
|
"",
|
|
40
90
|
"WHEN NOT TO USE:",
|
|
41
91
|
"- If the user wants full project files (multiple source files, build configs), use get_sample_files instead.",
|
|
@@ -43,20 +93,20 @@ export function registerQuickstartTools({
|
|
|
43
93
|
"- If the user only needs version info, use resolve_version.",
|
|
44
94
|
"",
|
|
45
95
|
"PARAMETERS:",
|
|
46
|
-
"- product (required):
|
|
96
|
+
"- product (required): dbr, dwt, ddv, mrz, or mds.",
|
|
47
97
|
"- edition: core, mobile, web, or server. Inferred from platform if omitted.",
|
|
48
98
|
"- platform: android, ios, js, python, cpp, java, dotnet, nodejs, react, vue, angular, flutter, react-native, maui, etc.",
|
|
49
99
|
"- language: kotlin, java, swift, js, ts, python, cpp, csharp, react, vue, angular. Helps select the best sample variant.",
|
|
50
100
|
"- version: Version constraint. Latest major is used by default.",
|
|
51
101
|
"- api_level: 'high-level' or 'low-level' (mobile only). Controls API abstraction level in generated code.",
|
|
52
|
-
"- scenario: MRZ,
|
|
102
|
+
"- scenario: MRZ, document scan, camera, image, single, multiple, react, vue, angular, etc. DBR web defaults to foundational guidance; MRZ and MDS return public workflow guidance where available.",
|
|
53
103
|
"",
|
|
54
104
|
"RETURNS: A formatted text block with SDK version, trial license key, install commands, and sample code. Ready to copy-paste.",
|
|
55
105
|
"",
|
|
56
106
|
"RELATED TOOLS: search (find specific docs or samples), get_sample_files (get full multi-file project), resolve_version (version numbers only)."
|
|
57
107
|
].join("\n"),
|
|
58
108
|
inputSchema: {
|
|
59
|
-
product: z.string().trim().min(1, "Product is required.").describe("Product:
|
|
109
|
+
product: z.string().trim().min(1, "Product is required.").describe("Product: dbr, dwt, ddv, mrz, mds"),
|
|
60
110
|
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
61
111
|
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"),
|
|
62
112
|
language: z.string().optional().describe("Language hint: kotlin, java, swift, js, ts, python, cpp, csharp, react, vue, angular"),
|
|
@@ -73,8 +123,18 @@ export function registerQuickstartTools({
|
|
|
73
123
|
},
|
|
74
124
|
async ({ product, edition, platform, language, version, api_level, scenario }) => {
|
|
75
125
|
const normalizedProduct = normalizeProduct(product);
|
|
126
|
+
if (product && !isKnownPublicOffering(normalizedProduct)) {
|
|
127
|
+
return buildUnknownPublicProductResponse(product);
|
|
128
|
+
}
|
|
129
|
+
|
|
76
130
|
const normalizedPlatform = normalizePlatform(platform);
|
|
77
131
|
const normalizedEdition = normalizeEdition(edition, normalizedPlatform, normalizedProduct);
|
|
132
|
+
const unsupportedScopeResponse = buildUnsupportedPublicScopeResponse(normalizedProduct, normalizedEdition, normalizedPlatform);
|
|
133
|
+
if (unsupportedScopeResponse) return unsupportedScopeResponse;
|
|
134
|
+
|
|
135
|
+
const isPublicDcvProduct = normalizedProduct === "mrz" || normalizedProduct === "mds";
|
|
136
|
+
const effectiveProduct = isPublicDcvProduct ? "dcv" : normalizedProduct;
|
|
137
|
+
const publicProductLabel = getPublicProductLabel(normalizedProduct);
|
|
78
138
|
|
|
79
139
|
await ensureScopeHydrated({
|
|
80
140
|
product: normalizedProduct,
|
|
@@ -95,9 +155,12 @@ export function registerQuickstartTools({
|
|
|
95
155
|
return { isError: true, content: [{ type: "text", text: policy.message }] };
|
|
96
156
|
}
|
|
97
157
|
|
|
98
|
-
if (
|
|
99
|
-
const
|
|
100
|
-
|
|
158
|
+
if (effectiveProduct === "dcv") {
|
|
159
|
+
const seededScenario = isPublicDcvProduct
|
|
160
|
+
? `${normalizedProduct === "mrz" ? "mrz" : "document scan"} ${scenario || ""} ${language || ""}`
|
|
161
|
+
: `${scenario || ""} ${language || ""}`;
|
|
162
|
+
const scenarioLower = seededScenario.toLowerCase();
|
|
163
|
+
const effectiveEdition = normalizedEdition || (isPublicDcvProduct ? "web" : (normalizedPlatform ? normalizeEdition("", normalizedPlatform, "dcv") : "server"));
|
|
101
164
|
|
|
102
165
|
function selectDcvServerSample(platformHint, hint) {
|
|
103
166
|
const platformName = normalizePlatform(platformHint) || "python";
|
|
@@ -173,6 +236,17 @@ export function registerQuickstartTools({
|
|
|
173
236
|
if (effectiveEdition === "server") {
|
|
174
237
|
const sdkEntry = registry.sdks["dcv-server"];
|
|
175
238
|
const targetPlatform = normalizePlatform(normalizedPlatform || sdkEntry.default_platform || "python");
|
|
239
|
+
|
|
240
|
+
if (isPublicDcvProduct) {
|
|
241
|
+
return buildPublicReferenceQuickstart({
|
|
242
|
+
product: normalizedProduct,
|
|
243
|
+
edition: effectiveEdition,
|
|
244
|
+
platform: targetPlatform,
|
|
245
|
+
docsUrl: "https://www.dynamsoft.com/capture-vision/docs/server/",
|
|
246
|
+
samplesUrl: sdkEntry.platforms?.[targetPlatform]?.samples?.repo || sdkEntry.platforms?.python?.samples?.repo || ""
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
176
250
|
const sampleName = selectDcvServerSample(targetPlatform, scenarioLower);
|
|
177
251
|
const samplePath = getDcvServerSamplePath(targetPlatform, sampleName);
|
|
178
252
|
|
|
@@ -187,7 +261,7 @@ export function registerQuickstartTools({
|
|
|
187
261
|
content: [{
|
|
188
262
|
type: "text",
|
|
189
263
|
text: [
|
|
190
|
-
`# Quick Start: DCV Server (${targetPlatform})`,
|
|
264
|
+
`# Quick Start: ${isPublicDcvProduct ? publicProductLabel : "DCV Server"} (${targetPlatform})`,
|
|
191
265
|
"",
|
|
192
266
|
`**SDK Version:** ${sdkEntry.version}`,
|
|
193
267
|
`**Trial License:** \`${registry.trial_license}\``,
|
|
@@ -210,8 +284,20 @@ export function registerQuickstartTools({
|
|
|
210
284
|
|
|
211
285
|
if (effectiveEdition === "web") {
|
|
212
286
|
const sdkEntry = registry.sdks["dcv-web"];
|
|
287
|
+
if (isPublicDcvProduct) {
|
|
288
|
+
const publicLinks = getPublicWebQuickstartLinks(normalizedProduct);
|
|
289
|
+
return buildPublicReferenceQuickstart({
|
|
290
|
+
product: normalizedProduct,
|
|
291
|
+
edition: effectiveEdition,
|
|
292
|
+
platform: "web",
|
|
293
|
+
docsUrl: publicLinks.docsUrl,
|
|
294
|
+
samplesUrl: publicLinks.samplesUrl
|
|
295
|
+
});
|
|
296
|
+
}
|
|
213
297
|
const available = discoverDcvWebSamples();
|
|
214
|
-
const sampleName =
|
|
298
|
+
const sampleName = isPublicDcvProduct
|
|
299
|
+
? (normalizedProduct === "mrz" ? "MRZScanner" : "DocumentScanner")
|
|
300
|
+
: (scenarioLower.includes("vin") ? "VINScanner" : (available[0] || "VINScanner"));
|
|
215
301
|
const samplePath = getDcvWebSamplePath(sampleName);
|
|
216
302
|
if (!samplePath || !existsSync(samplePath)) {
|
|
217
303
|
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
@@ -223,7 +309,7 @@ export function registerQuickstartTools({
|
|
|
223
309
|
content: [{
|
|
224
310
|
type: "text",
|
|
225
311
|
text: [
|
|
226
|
-
|
|
312
|
+
`# Quick Start: ${isPublicDcvProduct ? publicProductLabel : "DCV Web"}`,
|
|
227
313
|
"",
|
|
228
314
|
`**SDK Version:** ${sdkEntry.version}`,
|
|
229
315
|
`**Trial License:** \`${registry.trial_license}\``,
|
|
@@ -262,7 +348,7 @@ export function registerQuickstartTools({
|
|
|
262
348
|
content: [{
|
|
263
349
|
type: "text",
|
|
264
350
|
text: [
|
|
265
|
-
`# Quick Start: DCV Mobile (${targetPlatform})`,
|
|
351
|
+
`# Quick Start: ${isPublicDcvProduct ? publicProductLabel : "DCV Mobile"} (${targetPlatform})`,
|
|
266
352
|
"",
|
|
267
353
|
`**SDK Version:** ${sdkEntry.version}`,
|
|
268
354
|
`**Trial License:** \`${registry.trial_license}\``,
|
|
@@ -289,7 +375,7 @@ export function registerQuickstartTools({
|
|
|
289
375
|
content: [{
|
|
290
376
|
type: "text",
|
|
291
377
|
text: [
|
|
292
|
-
|
|
378
|
+
`# Quick Start: ${isPublicDcvProduct ? publicProductLabel : "DCV Core"}`,
|
|
293
379
|
"",
|
|
294
380
|
`**SDK Version:** ${sdkEntry.version}`,
|
|
295
381
|
"",
|
|
@@ -341,7 +427,7 @@ export function registerQuickstartTools({
|
|
|
341
427
|
if (normalizedProduct === "dbr" && normalizedEdition === "web") {
|
|
342
428
|
const sdkEntry = registry.sdks["dbr-web"];
|
|
343
429
|
const scenarioLower = (scenario || "").toLowerCase();
|
|
344
|
-
const sampleName = scenarioLower.includes("
|
|
430
|
+
const sampleName = scenarioLower.includes("hello") ? "hello-world" : "read-an-image";
|
|
345
431
|
const samplePath = getWebSamplePath("root", sampleName);
|
|
346
432
|
|
|
347
433
|
if (!samplePath || !existsSync(samplePath)) {
|
|
@@ -358,6 +444,9 @@ export function registerQuickstartTools({
|
|
|
358
444
|
"",
|
|
359
445
|
`**SDK Version:** ${sdkEntry.version}`,
|
|
360
446
|
`**Trial License:** \`${registry.trial_license}\``,
|
|
447
|
+
"**Starter profile:** Foundational-first",
|
|
448
|
+
"",
|
|
449
|
+
"Use the foundational web flow first so capture and decoding remain explicit and easier to adapt.",
|
|
361
450
|
"",
|
|
362
451
|
"## Option 1: CDN",
|
|
363
452
|
"```html",
|
|
@@ -369,7 +458,7 @@ export function registerQuickstartTools({
|
|
|
369
458
|
sdkEntry.platforms.web.installation.npm,
|
|
370
459
|
"```",
|
|
371
460
|
"",
|
|
372
|
-
`## ${sampleName}.html`,
|
|
461
|
+
`## Foundational sample: ${sampleName}.html`,
|
|
373
462
|
"```html",
|
|
374
463
|
content,
|
|
375
464
|
"```",
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { buildUnknownPublicProductResponse, isKnownPublicOffering } from "../public-offerings.js";
|
|
3
|
+
import { buildUnsupportedPublicScopeResponse } from "./public-routing.js";
|
|
2
4
|
|
|
3
5
|
export function registerSampleTools({
|
|
4
6
|
server,
|
|
7
|
+
registry,
|
|
5
8
|
ensureScopeHydrated,
|
|
6
9
|
ensureLatestMajor,
|
|
7
10
|
normalizeProduct,
|
|
@@ -23,14 +26,14 @@ export function registerSampleTools({
|
|
|
23
26
|
"- To browse the full catalog of samples available for a product/edition/platform.",
|
|
24
27
|
"- To discover sample IDs before calling get_sample_files.",
|
|
25
28
|
"- When the user wants to see what samples exist without a specific keyword.",
|
|
26
|
-
"- Use
|
|
29
|
+
"- Use MRZ for passport and machine-readable-zone workflows, and MDS for document scan and normalization workflows.",
|
|
27
30
|
"",
|
|
28
31
|
"WHEN NOT TO USE:",
|
|
29
32
|
"- If you have a specific keyword or topic, use search instead (it ranks results by relevance).",
|
|
30
33
|
"- If you already have a sample ID or URI, go directly to get_sample_files.",
|
|
31
34
|
"",
|
|
32
35
|
"PARAMETERS:",
|
|
33
|
-
"- product:
|
|
36
|
+
"- product: dbr, dwt, ddv, mrz, or mds. Omit to list across all public offerings.",
|
|
34
37
|
"- edition: core, mobile, web, or server. Omit to list across all editions.",
|
|
35
38
|
"- platform: android, ios, js, python, cpp, java, dotnet, nodejs, react, vue, angular, flutter, react-native, maui, etc.",
|
|
36
39
|
"- limit: 1-200 (default 50). Max number of results.",
|
|
@@ -42,7 +45,7 @@ export function registerSampleTools({
|
|
|
42
45
|
"RELATED TOOLS: search (keyword-based discovery), get_sample_files (retrieve full project files for a sample), get_index (discover valid product/edition/platform combinations)."
|
|
43
46
|
].join("\n"),
|
|
44
47
|
inputSchema: {
|
|
45
|
-
product: z.string().optional().describe("Product:
|
|
48
|
+
product: z.string().optional().describe("Product: dbr, dwt, ddv, mrz, mds"),
|
|
46
49
|
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
47
50
|
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"),
|
|
48
51
|
limit: z.number().int().min(1).max(200).optional().describe("Max results (default 50)")
|
|
@@ -56,8 +59,14 @@ export function registerSampleTools({
|
|
|
56
59
|
},
|
|
57
60
|
async ({ product, edition, platform, limit }) => {
|
|
58
61
|
const normalizedProduct = normalizeProduct(product);
|
|
62
|
+
if (product && !isKnownPublicOffering(normalizedProduct)) {
|
|
63
|
+
return buildUnknownPublicProductResponse(product);
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
const normalizedPlatform = normalizePlatform(platform);
|
|
60
67
|
const normalizedEdition = normalizeEdition(edition, normalizedPlatform, normalizedProduct);
|
|
68
|
+
const unsupportedScopeResponse = buildUnsupportedPublicScopeResponse(normalizedProduct, normalizedEdition, normalizedPlatform);
|
|
69
|
+
if (unsupportedScopeResponse) return unsupportedScopeResponse;
|
|
61
70
|
|
|
62
71
|
await ensureScopeHydrated({
|
|
63
72
|
product: normalizedProduct,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { buildUnknownPublicProductResponse, isKnownPublicOffering } from "../public-offerings.js";
|
|
2
3
|
|
|
3
4
|
export function registerVersionTools({
|
|
4
5
|
server,
|
|
@@ -9,6 +10,47 @@ export function registerVersionTools({
|
|
|
9
10
|
LATEST_MAJOR,
|
|
10
11
|
LATEST_VERSIONS
|
|
11
12
|
}) {
|
|
13
|
+
function buildPublicDcvVersionResponse(product, edition, platform) {
|
|
14
|
+
const label = product === "mrz" ? "MRZ" : "MDS";
|
|
15
|
+
const supportedEditions = product === "mrz"
|
|
16
|
+
? [
|
|
17
|
+
{ key: "web", name: "Web", version: LATEST_VERSIONS.dcv.web },
|
|
18
|
+
{ key: "mobile", name: "Mobile", version: LATEST_VERSIONS.dcv.mobile }
|
|
19
|
+
]
|
|
20
|
+
: [{ key: "web", name: "Web", version: LATEST_VERSIONS.dcv.web }];
|
|
21
|
+
const supportedEditionKeys = supportedEditions.map((entry) => entry.key).join(", ");
|
|
22
|
+
|
|
23
|
+
if (!edition) {
|
|
24
|
+
const lines = [
|
|
25
|
+
`# ${label} Version Resolution`,
|
|
26
|
+
`- Latest major: v${LATEST_MAJOR.dcv}`,
|
|
27
|
+
...supportedEditions.map((entry) => `- ${entry.name}: ${entry.version}`),
|
|
28
|
+
"",
|
|
29
|
+
"Specify edition/platform to resolve a single version."
|
|
30
|
+
];
|
|
31
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const supportedEdition = supportedEditions.find((entry) => entry.key === edition);
|
|
35
|
+
if (!supportedEdition) {
|
|
36
|
+
return {
|
|
37
|
+
isError: true,
|
|
38
|
+
content: [{ type: "text", text: `Edition "${edition}" is not hosted by this MCP server. Supported editions: ${supportedEditionKeys}.` }]
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const displayPlatform = platform === "web" ? "js" : platform;
|
|
43
|
+
const lines = [
|
|
44
|
+
`# ${label} Version Resolution`,
|
|
45
|
+
`- Edition: ${edition}`,
|
|
46
|
+
displayPlatform ? `- Platform: ${displayPlatform}` : "",
|
|
47
|
+
`- Latest major: v${LATEST_MAJOR.dcv}`,
|
|
48
|
+
`- Resolved version: ${supportedEdition.version}`
|
|
49
|
+
].filter(Boolean);
|
|
50
|
+
|
|
51
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
52
|
+
}
|
|
53
|
+
|
|
12
54
|
server.registerTool(
|
|
13
55
|
"resolve_version",
|
|
14
56
|
{
|
|
@@ -26,20 +68,20 @@ export function registerVersionTools({
|
|
|
26
68
|
"- For browsing docs or samples, use search or list_samples (they already scope to latest major).",
|
|
27
69
|
"",
|
|
28
70
|
"PARAMETERS:",
|
|
29
|
-
"- product (required):
|
|
71
|
+
"- product (required): dbr, dwt, ddv, mrz, or mds.",
|
|
30
72
|
"- edition: core, mobile, web, or server. Omit to see all editions for the product.",
|
|
31
73
|
"- platform: android, ios, js, python, cpp, java, dotnet, nodejs, etc. Helps narrow edition when ambiguous.",
|
|
32
74
|
"- constraint: Version constraint like 'latest', '11.x', '10'. Only latest major version is served; legacy versions (e.g. DBR v9) return an error with migration guidance.",
|
|
33
75
|
"- feature: Optional feature hint for version policy checks.",
|
|
34
76
|
"",
|
|
35
|
-
"RETURNS: A text block showing the resolved version. For
|
|
77
|
+
"RETURNS: A text block showing the resolved version. For MRZ/MDS without an edition, returns the backed public version matrix. For DBR without an edition, returns all edition versions. For DWT/DDV, returns the single web version.",
|
|
36
78
|
"",
|
|
37
79
|
"EXAMPLE: resolve_version with product='dbr', edition='web' returns the latest DBR web SDK version string.",
|
|
38
80
|
"",
|
|
39
81
|
"RELATED TOOLS: get_quickstart (includes version in starter code), get_index (shows version overview)."
|
|
40
82
|
].join("\n"),
|
|
41
83
|
inputSchema: {
|
|
42
|
-
product: z.string().trim().min(1, "Product is required.").describe("Product:
|
|
84
|
+
product: z.string().trim().min(1, "Product is required.").describe("Product: dbr, dwt, ddv, mrz, mds"),
|
|
43
85
|
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
44
86
|
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"),
|
|
45
87
|
constraint: z.string().optional().describe("Version constraint, e.g., latest, 11.x, 10"),
|
|
@@ -54,16 +96,13 @@ export function registerVersionTools({
|
|
|
54
96
|
},
|
|
55
97
|
async ({ product, edition, platform, constraint, feature }) => {
|
|
56
98
|
const normalizedProduct = normalizeProduct(product);
|
|
99
|
+
if (product && !isKnownPublicOffering(normalizedProduct)) {
|
|
100
|
+
return buildUnknownPublicProductResponse(product);
|
|
101
|
+
}
|
|
102
|
+
|
|
57
103
|
const normalizedPlatform = normalizePlatform(platform);
|
|
58
104
|
const normalizedEdition = normalizeEdition(edition, normalizedPlatform, normalizedProduct);
|
|
59
105
|
|
|
60
|
-
if (!["dcv", "dbr", "dwt", "ddv"].includes(normalizedProduct)) {
|
|
61
|
-
return {
|
|
62
|
-
isError: true,
|
|
63
|
-
content: [{ type: "text", text: `Unknown product "${product}". Use dcv, dbr, dwt, or ddv.` }]
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
106
|
const policy = ensureLatestMajor({
|
|
68
107
|
product: normalizedProduct,
|
|
69
108
|
version: constraint,
|
|
@@ -76,39 +115,8 @@ export function registerVersionTools({
|
|
|
76
115
|
return { isError: true, content: [{ type: "text", text: policy.message }] };
|
|
77
116
|
}
|
|
78
117
|
|
|
79
|
-
if (normalizedProduct === "
|
|
80
|
-
|
|
81
|
-
const lines = [
|
|
82
|
-
"# DCV Version Resolution",
|
|
83
|
-
`- Latest major: v${LATEST_MAJOR.dcv}`,
|
|
84
|
-
`- Core: ${LATEST_VERSIONS.dcv.core}`,
|
|
85
|
-
`- Web: ${LATEST_VERSIONS.dcv.web}`,
|
|
86
|
-
`- Mobile: ${LATEST_VERSIONS.dcv.mobile}`,
|
|
87
|
-
`- Server/Desktop: ${LATEST_VERSIONS.dcv.server}`,
|
|
88
|
-
"",
|
|
89
|
-
"Specify edition/platform to resolve a single version."
|
|
90
|
-
];
|
|
91
|
-
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const resolved = LATEST_VERSIONS.dcv[normalizedEdition];
|
|
95
|
-
if (!resolved) {
|
|
96
|
-
return {
|
|
97
|
-
isError: true,
|
|
98
|
-
content: [{ type: "text", text: `Edition "${normalizedEdition}" is not hosted by this MCP server.` }]
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const displayPlatform = normalizedPlatform === "web" ? "js" : normalizedPlatform;
|
|
103
|
-
const lines = [
|
|
104
|
-
"# DCV Version Resolution",
|
|
105
|
-
`- Edition: ${normalizedEdition}`,
|
|
106
|
-
displayPlatform ? `- Platform: ${displayPlatform}` : "",
|
|
107
|
-
`- Latest major: v${LATEST_MAJOR.dcv}`,
|
|
108
|
-
`- Resolved version: ${resolved}`
|
|
109
|
-
].filter(Boolean);
|
|
110
|
-
|
|
111
|
-
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
118
|
+
if (normalizedProduct === "mrz" || normalizedProduct === "mds") {
|
|
119
|
+
return buildPublicDcvVersionResponse(normalizedProduct, normalizedEdition, normalizedPlatform);
|
|
112
120
|
}
|
|
113
121
|
|
|
114
122
|
if (normalizedProduct === "dbr") {
|