@jsonrecon/mcp-server 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,473 @@
1
+ // Generated by scripts/sync-mcp-output-schemas.js from lib/bazaar-output-schemas.js.
2
+ // Do not edit this file directly; update the canonical schemas and run npm run schemas:sync.
3
+ export const FULL_OUTPUT_SCHEMA = {
4
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
5
+ "title": "JSON Recon Full extraction result",
6
+ "description": "A successful Full extraction response containing one primary Schema.org JSON-LD entity and extraction metadata.",
7
+ "type": "object",
8
+ "properties": {
9
+ "success": {
10
+ "type": "boolean",
11
+ "const": true
12
+ },
13
+ "data": {
14
+ "type": "object",
15
+ "description": "A Schema.org JSON-LD entity. Its fields vary with schema_type.",
16
+ "properties": {
17
+ "@context": {},
18
+ "@type": {
19
+ "oneOf": [
20
+ {
21
+ "type": "string"
22
+ },
23
+ {
24
+ "type": "array",
25
+ "items": {
26
+ "type": "string"
27
+ },
28
+ "minItems": 1
29
+ }
30
+ ]
31
+ }
32
+ },
33
+ "additionalProperties": true
34
+ },
35
+ "schema_type": {
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "description": "The primary Schema.org type represented by data."
39
+ },
40
+ "confidence": {
41
+ "type": "string",
42
+ "enum": [
43
+ "high",
44
+ "medium",
45
+ "low"
46
+ ]
47
+ },
48
+ "cached": {
49
+ "type": "boolean"
50
+ },
51
+ "extraction_ms": {
52
+ "type": "number",
53
+ "minimum": 0
54
+ },
55
+ "source": {
56
+ "type": "string",
57
+ "description": "The public provenance category for the extracted entity."
58
+ },
59
+ "page_schemas": {
60
+ "type": "array",
61
+ "items": {
62
+ "type": "string"
63
+ },
64
+ "uniqueItems": true
65
+ },
66
+ "extracted_at": {
67
+ "type": "string"
68
+ },
69
+ "_meta": {
70
+ "type": "object",
71
+ "additionalProperties": true
72
+ },
73
+ "recommendation": {
74
+ "type": "string"
75
+ },
76
+ "suggested_type": {
77
+ "type": "string",
78
+ "minLength": 1
79
+ },
80
+ "suggested_reason": {
81
+ "type": "string"
82
+ },
83
+ "suggested_data": {
84
+ "type": "object",
85
+ "description": "A Schema.org JSON-LD entity. Its fields vary with schema_type.",
86
+ "properties": {
87
+ "@context": {},
88
+ "@type": {
89
+ "oneOf": [
90
+ {
91
+ "type": "string"
92
+ },
93
+ {
94
+ "type": "array",
95
+ "items": {
96
+ "type": "string"
97
+ },
98
+ "minItems": 1
99
+ }
100
+ ]
101
+ }
102
+ },
103
+ "additionalProperties": true
104
+ }
105
+ },
106
+ "required": [
107
+ "success",
108
+ "data",
109
+ "schema_type",
110
+ "confidence",
111
+ "cached",
112
+ "extraction_ms"
113
+ ],
114
+ "additionalProperties": true
115
+ };
116
+ export const LITE_OUTPUT_SCHEMA = {
117
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
118
+ "title": "JSON Recon Lite retrieval result",
119
+ "description": "A successful Lite response containing Schema.org JSON-LD published by the requested page and an explicit quality signal when the result is navigation-only.",
120
+ "type": "object",
121
+ "properties": {
122
+ "success": {
123
+ "type": "boolean",
124
+ "const": true
125
+ },
126
+ "data": {
127
+ "type": "object",
128
+ "description": "A Schema.org JSON-LD entity. Its fields vary with schema_type.",
129
+ "properties": {
130
+ "@context": {},
131
+ "@type": {
132
+ "oneOf": [
133
+ {
134
+ "type": "string"
135
+ },
136
+ {
137
+ "type": "array",
138
+ "items": {
139
+ "type": "string"
140
+ },
141
+ "minItems": 1
142
+ }
143
+ ]
144
+ }
145
+ },
146
+ "additionalProperties": true
147
+ },
148
+ "schema_type": {
149
+ "type": "string",
150
+ "minLength": 1,
151
+ "description": "The primary Schema.org type represented by data."
152
+ },
153
+ "confidence": {
154
+ "type": "string",
155
+ "enum": [
156
+ "high",
157
+ "medium",
158
+ "low"
159
+ ]
160
+ },
161
+ "cached": {
162
+ "type": "boolean"
163
+ },
164
+ "extraction_ms": {
165
+ "type": "number",
166
+ "minimum": 0
167
+ },
168
+ "source": {
169
+ "type": "string",
170
+ "description": "The public provenance category for the extracted entity."
171
+ },
172
+ "page_schemas": {
173
+ "type": "array",
174
+ "items": {
175
+ "type": "string"
176
+ },
177
+ "uniqueItems": true
178
+ },
179
+ "extracted_at": {
180
+ "type": "string"
181
+ },
182
+ "_meta": {
183
+ "type": "object",
184
+ "additionalProperties": true
185
+ },
186
+ "recommendation": {
187
+ "type": "string"
188
+ },
189
+ "information_quality": {
190
+ "type": "object",
191
+ "properties": {
192
+ "level": {
193
+ "type": "string",
194
+ "enum": [
195
+ "low"
196
+ ]
197
+ },
198
+ "reason": {
199
+ "type": "string",
200
+ "enum": [
201
+ "navigation_or_container_schema_only"
202
+ ]
203
+ }
204
+ },
205
+ "required": [
206
+ "level",
207
+ "reason"
208
+ ],
209
+ "additionalProperties": false
210
+ }
211
+ },
212
+ "required": [
213
+ "success",
214
+ "data",
215
+ "schema_type",
216
+ "confidence",
217
+ "cached",
218
+ "extraction_ms"
219
+ ],
220
+ "additionalProperties": true
221
+ };
222
+ export const VERIFIED_OUTPUT_SCHEMA = {
223
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
224
+ "title": "JSON Recon Verified Product result",
225
+ "description": "A successful Product verification response with a page-consistency verdict, field evidence, contradictions, coverage, observation time, and content hash.",
226
+ "type": "object",
227
+ "properties": {
228
+ "success": {
229
+ "type": "boolean",
230
+ "const": true
231
+ },
232
+ "data": {
233
+ "type": "object",
234
+ "description": "The sanitized Product entity whose fields were assessed.",
235
+ "properties": {
236
+ "@context": {},
237
+ "@type": {
238
+ "type": "string",
239
+ "const": "Product"
240
+ }
241
+ },
242
+ "additionalProperties": true,
243
+ "required": [
244
+ "@type"
245
+ ]
246
+ },
247
+ "schema_type": {
248
+ "type": "string",
249
+ "const": "Product"
250
+ },
251
+ "verification_version": {
252
+ "type": "string",
253
+ "pattern": "^product\\/v[0-9]+$"
254
+ },
255
+ "verdict": {
256
+ "type": "string",
257
+ "enum": [
258
+ "verified",
259
+ "conflicted",
260
+ "insufficient_evidence"
261
+ ]
262
+ },
263
+ "verification": {
264
+ "type": "object",
265
+ "properties": {
266
+ "scope": {
267
+ "type": "string",
268
+ "const": "page_consistency"
269
+ },
270
+ "observed_at": {
271
+ "type": "string"
272
+ },
273
+ "content_sha256": {
274
+ "type": "string",
275
+ "pattern": "^sha256:[a-f0-9]{64}$"
276
+ },
277
+ "fields": {
278
+ "type": "object",
279
+ "additionalProperties": {
280
+ "type": "object",
281
+ "properties": {
282
+ "value": {
283
+ "description": "A bounded value observed in one representation of the page."
284
+ },
285
+ "status": {
286
+ "type": "string",
287
+ "enum": [
288
+ "corroborated",
289
+ "conflicted",
290
+ "single_source"
291
+ ]
292
+ },
293
+ "sources": {
294
+ "type": "array",
295
+ "items": {
296
+ "type": "object",
297
+ "properties": {
298
+ "channel": {
299
+ "type": "string",
300
+ "enum": [
301
+ "json_ld",
302
+ "metadata",
303
+ "microdata",
304
+ "visible_text"
305
+ ]
306
+ },
307
+ "value": {
308
+ "description": "A bounded value observed in one representation of the page."
309
+ },
310
+ "excerpt": {
311
+ "type": "string",
312
+ "maxLength": 160
313
+ }
314
+ },
315
+ "required": [
316
+ "channel",
317
+ "value"
318
+ ],
319
+ "additionalProperties": false
320
+ }
321
+ }
322
+ },
323
+ "required": [
324
+ "value",
325
+ "status",
326
+ "sources"
327
+ ],
328
+ "additionalProperties": false
329
+ }
330
+ },
331
+ "contradictions": {
332
+ "type": "array",
333
+ "items": {
334
+ "type": "object",
335
+ "properties": {
336
+ "field": {
337
+ "type": "string"
338
+ },
339
+ "severity": {
340
+ "type": "string",
341
+ "const": "critical"
342
+ },
343
+ "values": {
344
+ "type": "array",
345
+ "items": {
346
+ "type": "object",
347
+ "properties": {
348
+ "channel": {
349
+ "type": "string",
350
+ "enum": [
351
+ "json_ld",
352
+ "metadata",
353
+ "microdata",
354
+ "visible_text"
355
+ ]
356
+ },
357
+ "value": {
358
+ "description": "A bounded value observed in one representation of the page."
359
+ }
360
+ },
361
+ "required": [
362
+ "channel",
363
+ "value"
364
+ ],
365
+ "additionalProperties": false
366
+ }
367
+ }
368
+ },
369
+ "required": [
370
+ "field",
371
+ "severity",
372
+ "values"
373
+ ],
374
+ "additionalProperties": false
375
+ }
376
+ },
377
+ "coverage": {
378
+ "type": "object",
379
+ "properties": {
380
+ "corroborated": {
381
+ "type": "integer",
382
+ "minimum": 0
383
+ },
384
+ "conflicted": {
385
+ "type": "integer",
386
+ "minimum": 0
387
+ },
388
+ "single_source": {
389
+ "type": "integer",
390
+ "minimum": 0
391
+ }
392
+ },
393
+ "required": [
394
+ "corroborated",
395
+ "conflicted",
396
+ "single_source"
397
+ ],
398
+ "additionalProperties": false
399
+ },
400
+ "ambiguous_offer": {
401
+ "type": "boolean"
402
+ },
403
+ "efficiency": {
404
+ "type": "object",
405
+ "properties": {
406
+ "estimate_method": {
407
+ "type": "string",
408
+ "const": "characters_divided_by_4"
409
+ },
410
+ "page_characters": {
411
+ "type": "integer",
412
+ "minimum": 0
413
+ },
414
+ "response_characters": {
415
+ "type": "integer",
416
+ "minimum": 0
417
+ },
418
+ "estimated_page_tokens": {
419
+ "type": "integer",
420
+ "minimum": 0
421
+ },
422
+ "estimated_response_tokens": {
423
+ "type": "integer",
424
+ "minimum": 0
425
+ },
426
+ "estimated_tokens_avoided": {
427
+ "type": "integer",
428
+ "minimum": 0
429
+ }
430
+ },
431
+ "required": [
432
+ "estimate_method",
433
+ "page_characters",
434
+ "response_characters",
435
+ "estimated_page_tokens",
436
+ "estimated_response_tokens",
437
+ "estimated_tokens_avoided"
438
+ ],
439
+ "additionalProperties": false
440
+ }
441
+ },
442
+ "required": [
443
+ "scope",
444
+ "observed_at",
445
+ "content_sha256",
446
+ "fields",
447
+ "contradictions",
448
+ "coverage",
449
+ "ambiguous_offer",
450
+ "efficiency"
451
+ ],
452
+ "additionalProperties": false
453
+ },
454
+ "cached": {
455
+ "type": "boolean"
456
+ },
457
+ "extraction_ms": {
458
+ "type": "number",
459
+ "minimum": 0
460
+ }
461
+ },
462
+ "required": [
463
+ "success",
464
+ "data",
465
+ "schema_type",
466
+ "verification_version",
467
+ "verdict",
468
+ "verification",
469
+ "cached",
470
+ "extraction_ms"
471
+ ],
472
+ "additionalProperties": false
473
+ };
package/dist/index.js ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import axios from "axios";
6
+ import { TOOLS } from "./tools.js";
7
+ // Environment setup
8
+ const API_KEY = process.env.JSONRECON_API_KEY;
9
+ // For dev/testing, user might override the endpoint
10
+ const ENDPOINT = process.env.JSONRECON_ENDPOINT || "https://jsonrecon.com";
11
+ if (!API_KEY) {
12
+ console.error("Missing JSONRECON_API_KEY environment variable.");
13
+ console.error("Please add it to your MCP configuration.");
14
+ process.exit(1);
15
+ }
16
+ const server = new Server({
17
+ name: "jsonrecon-mcp",
18
+ version: "1.2.0",
19
+ }, {
20
+ capabilities: {
21
+ tools: {},
22
+ },
23
+ });
24
+ // Register tools
25
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
26
+ return { tools: TOOLS };
27
+ });
28
+ // Handle tool execution
29
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
30
+ if (request.params.name === "extract_schema") {
31
+ const url = String(request.params.arguments?.url);
32
+ const schemaType = String(request.params.arguments?.schema_type || "auto");
33
+ const mode = String(request.params.arguments?.mode || "full");
34
+ try {
35
+ const endpointPath = mode === "lite" ? "/extract/lite" : "/extract";
36
+ const response = await axios.post(`${ENDPOINT}${endpointPath}`, {
37
+ url: url,
38
+ schema_type: schemaType,
39
+ }, {
40
+ headers: {
41
+ "Authorization": `Bearer ${API_KEY}`,
42
+ "Content-Type": "application/json"
43
+ },
44
+ });
45
+ return {
46
+ structuredContent: response.data,
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: JSON.stringify(response.data, null, 2),
51
+ },
52
+ ],
53
+ };
54
+ }
55
+ catch (error) {
56
+ const errorMsg = error.response?.data?.error || error.message;
57
+ return {
58
+ isError: true,
59
+ content: [
60
+ {
61
+ type: "text",
62
+ text: `JsonRecon API Error: ${errorMsg}`,
63
+ },
64
+ ],
65
+ };
66
+ }
67
+ }
68
+ if (request.params.name === "verify_product") {
69
+ const url = String(request.params.arguments?.url);
70
+ try {
71
+ const response = await axios.post(`${ENDPOINT}/extract/verified`, { url }, { headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" } });
72
+ return {
73
+ structuredContent: response.data,
74
+ content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }],
75
+ };
76
+ }
77
+ catch (error) {
78
+ const body = error.response?.data;
79
+ const errorMsg = body?.error || error.message;
80
+ return {
81
+ isError: true,
82
+ content: [{ type: "text", text: JSON.stringify({ error: errorMsg, reason: body?.reason, refunded: body?.refunded }, null, 2) }],
83
+ };
84
+ }
85
+ }
86
+ if (request.params.name === "check_extractability") {
87
+ const url = String(request.params.arguments?.url);
88
+ try {
89
+ const response = await axios.get(`${ENDPOINT}/check`, { params: { url } });
90
+ return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
91
+ }
92
+ catch (error) {
93
+ const errorMsg = error.response?.data?.error || error.message;
94
+ return { isError: true, content: [{ type: "text", text: `JsonRecon API Error: ${errorMsg}` }] };
95
+ }
96
+ }
97
+ throw new Error(`Tool not found: ${request.params.name}`);
98
+ });
99
+ async function main() {
100
+ const transport = new StdioServerTransport();
101
+ await server.connect(transport);
102
+ console.error("JsonRecon MCP server running on stdio");
103
+ }
104
+ main().catch((error) => {
105
+ console.error("Server error:", error);
106
+ process.exit(1);
107
+ });
package/dist/tools.js ADDED
@@ -0,0 +1,62 @@
1
+ import { FULL_OUTPUT_SCHEMA, LITE_OUTPUT_SCHEMA, VERIFIED_OUTPUT_SCHEMA, } from "./generated/output-schemas.js";
2
+ const asOutputSchema = (schema) => schema;
3
+ const EXTRACTION_OUTPUT_SCHEMA = asOutputSchema({
4
+ $schema: "https://json-schema.org/draft/2020-12/schema",
5
+ title: "JSON Recon extraction result",
6
+ type: "object",
7
+ anyOf: [FULL_OUTPUT_SCHEMA, LITE_OUTPUT_SCHEMA],
8
+ });
9
+ export const TOOLS = [
10
+ {
11
+ name: "extract_schema",
12
+ description: "Convert a public web page into concise Schema.org JSON-LD for agents and automation.",
13
+ inputSchema: {
14
+ type: "object",
15
+ properties: {
16
+ url: {
17
+ type: "string",
18
+ description: "The complete URL to extract structured data from.",
19
+ },
20
+ schema_type: {
21
+ type: "string",
22
+ description: "The specific Schema.org type to extract (e.g., 'Article', 'LocalBusiness', 'Product'). Use 'auto' to auto-detect.",
23
+ default: "auto",
24
+ },
25
+ mode: {
26
+ type: "string",
27
+ description: "Extraction mode: 'full' ($0.01) or 'lite' for existing page markup ($0.005). Default is 'full'.",
28
+ enum: ["full", "lite"],
29
+ default: "full",
30
+ },
31
+ },
32
+ required: ["url"],
33
+ },
34
+ outputSchema: EXTRACTION_OUTPUT_SCHEMA,
35
+ },
36
+ {
37
+ name: "verify_product",
38
+ description: "Verify Product fields against multiple representations on a public product page. Returns field-level corroboration, contradictions, bounded evidence, observation time, and a content hash. The $0.02 charge applies only to successful assessments; non-product pages do not consume balance.",
39
+ inputSchema: {
40
+ type: "object",
41
+ properties: {
42
+ url: {
43
+ type: "string",
44
+ description: "The complete public Product page URL to verify.",
45
+ },
46
+ },
47
+ required: ["url"],
48
+ },
49
+ outputSchema: asOutputSchema(VERIFIED_OUTPUT_SCHEMA),
50
+ },
51
+ {
52
+ name: "check_extractability",
53
+ description: "Free pre-flight assessment for a public URL before a paid request.",
54
+ inputSchema: {
55
+ type: "object",
56
+ properties: {
57
+ url: { type: "string", description: "The complete public URL to assess." },
58
+ },
59
+ required: ["url"],
60
+ },
61
+ },
62
+ ];
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@jsonrecon/mcp-server",
3
+ "version": "1.2.0",
4
+ "description": "MCP tools for concise Schema.org extraction and Product verification",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "jsonrecon-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "scripts": {
17
+ "schemas:check": "node ../../scripts/sync-mcp-output-schemas.js --check",
18
+ "prebuild": "npm run schemas:check",
19
+ "build": "tsc",
20
+ "test": "node --test test/*.test.mjs",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "dependencies": {
24
+ "@modelcontextprotocol/sdk": "^1.0.1",
25
+ "axios": "^1.7.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.0.0",
29
+ "typescript": "^5.0.0"
30
+ }
31
+ }