visus-mcp 0.6.2 → 0.8.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.
Files changed (177) hide show
  1. package/.claude/settings.local.json +6 -1
  2. package/.env.status +7 -0
  3. package/CHANGELOG.md +65 -0
  4. package/CLAUDE.md +3 -0
  5. package/README.md +15 -7
  6. package/SECURITY.md +2 -0
  7. package/STATUS.md +203 -9
  8. package/dist/content-handlers/index.d.ts +36 -0
  9. package/dist/content-handlers/index.d.ts.map +1 -0
  10. package/dist/content-handlers/index.js +59 -0
  11. package/dist/content-handlers/index.js.map +1 -0
  12. package/dist/content-handlers/json-handler.d.ts +28 -0
  13. package/dist/content-handlers/json-handler.d.ts.map +1 -0
  14. package/dist/content-handlers/json-handler.js +116 -0
  15. package/dist/content-handlers/json-handler.js.map +1 -0
  16. package/dist/content-handlers/pdf-handler.d.ts +29 -0
  17. package/dist/content-handlers/pdf-handler.d.ts.map +1 -0
  18. package/dist/content-handlers/pdf-handler.js +77 -0
  19. package/dist/content-handlers/pdf-handler.js.map +1 -0
  20. package/dist/content-handlers/svg-handler.d.ts +35 -0
  21. package/dist/content-handlers/svg-handler.d.ts.map +1 -0
  22. package/dist/content-handlers/svg-handler.js +206 -0
  23. package/dist/content-handlers/svg-handler.js.map +1 -0
  24. package/dist/content-handlers/types.d.ts +42 -0
  25. package/dist/content-handlers/types.d.ts.map +1 -0
  26. package/dist/content-handlers/types.js +7 -0
  27. package/dist/content-handlers/types.js.map +1 -0
  28. package/dist/tools/fetch.d.ts.map +1 -1
  29. package/dist/tools/fetch.js +62 -4
  30. package/dist/tools/fetch.js.map +1 -1
  31. package/package.json +2 -1
  32. package/server.json +2 -2
  33. package/src/content-handlers/index.ts +72 -0
  34. package/src/content-handlers/json-handler.ts +137 -0
  35. package/src/content-handlers/pdf-handler.ts +91 -0
  36. package/src/content-handlers/svg-handler.ts +243 -0
  37. package/src/content-handlers/types.ts +44 -0
  38. package/src/tools/fetch.ts +69 -4
  39. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -47
  40. package/.github/ISSUE_TEMPLATE/false_positive.md +0 -43
  41. package/.github/ISSUE_TEMPLATE/new_pattern.md +0 -49
  42. package/.github/ISSUE_TEMPLATE/security_report.md +0 -31
  43. package/.github/PULL_REQUEST_TEMPLATE.md +0 -39
  44. package/.mcpregistry_github_token +0 -1
  45. package/.mcpregistry_registry_token +0 -1
  46. package/CONTRIBUTING.md +0 -329
  47. package/LINKEDIN-STRATEGY.md +0 -367
  48. package/ROADMAP.md +0 -221
  49. package/SECURITY-AUDIT-v1.md +0 -277
  50. package/SUBMISSION.md +0 -66
  51. package/TROUBLESHOOT-AUTH-20260322-2019.md +0 -291
  52. package/TROUBLESHOOT-BUILD-20260319-1450.md +0 -546
  53. package/TROUBLESHOOT-COGNITO-AUTH-20260324-2029.md +0 -415
  54. package/TROUBLESHOOT-COGNITO-JWT-20260324.md +0 -592
  55. package/TROUBLESHOOT-FETCH-20260320-1150.md +0 -168
  56. package/TROUBLESHOOT-JEST-20260323-1357.md +0 -139
  57. package/TROUBLESHOOT-LAMBDA-20260322-1945.md +0 -183
  58. package/TROUBLESHOOT-PLAYWRIGHT-20260321-1549.md +0 -217
  59. package/TROUBLESHOOT-SSL-20260320-1138.md +0 -171
  60. package/TROUBLESHOOT-STRUCTURED-20260320-1200.md +0 -246
  61. package/TROUBLESHOOT-TEST-20260320-0942.md +0 -281
  62. package/VISUS-CLAUDE-CODE-PROMPT.md +0 -324
  63. package/VISUS-PROJECT-PLAN.md +0 -205
  64. package/cdk.json +0 -73
  65. package/infrastructure/app.ts +0 -39
  66. package/infrastructure/stack.ts +0 -298
  67. package/jest.config.js +0 -33
  68. package/jest.setup.js +0 -9
  69. package/lambda-deploy/index.js +0 -81512
  70. package/lambda-deploy/index.js.map +0 -7
  71. package/lambda-package/browser/__mocks__/playwright-renderer.d.ts +0 -25
  72. package/lambda-package/browser/__mocks__/playwright-renderer.d.ts.map +0 -1
  73. package/lambda-package/browser/__mocks__/playwright-renderer.js +0 -119
  74. package/lambda-package/browser/__mocks__/playwright-renderer.js.map +0 -1
  75. package/lambda-package/browser/playwright-renderer.d.ts +0 -40
  76. package/lambda-package/browser/playwright-renderer.d.ts.map +0 -1
  77. package/lambda-package/browser/playwright-renderer.js +0 -214
  78. package/lambda-package/browser/playwright-renderer.js.map +0 -1
  79. package/lambda-package/browser/reader.d.ts +0 -31
  80. package/lambda-package/browser/reader.d.ts.map +0 -1
  81. package/lambda-package/browser/reader.js +0 -98
  82. package/lambda-package/browser/reader.js.map +0 -1
  83. package/lambda-package/index.d.ts +0 -18
  84. package/lambda-package/index.d.ts.map +0 -1
  85. package/lambda-package/index.js +0 -238
  86. package/lambda-package/index.js.map +0 -1
  87. package/lambda-package/lambda-handler.d.ts +0 -28
  88. package/lambda-package/lambda-handler.d.ts.map +0 -1
  89. package/lambda-package/lambda-handler.js +0 -257
  90. package/lambda-package/lambda-handler.js.map +0 -1
  91. package/lambda-package/package-lock.json +0 -7435
  92. package/lambda-package/package.json +0 -74
  93. package/lambda-package/runtime.d.ts +0 -50
  94. package/lambda-package/runtime.d.ts.map +0 -1
  95. package/lambda-package/runtime.js +0 -86
  96. package/lambda-package/runtime.js.map +0 -1
  97. package/lambda-package/sanitizer/elicit-runner.d.ts +0 -48
  98. package/lambda-package/sanitizer/elicit-runner.d.ts.map +0 -1
  99. package/lambda-package/sanitizer/elicit-runner.js +0 -100
  100. package/lambda-package/sanitizer/elicit-runner.js.map +0 -1
  101. package/lambda-package/sanitizer/framework-mapper.d.ts +0 -24
  102. package/lambda-package/sanitizer/framework-mapper.d.ts.map +0 -1
  103. package/lambda-package/sanitizer/framework-mapper.js +0 -342
  104. package/lambda-package/sanitizer/framework-mapper.js.map +0 -1
  105. package/lambda-package/sanitizer/hitl-gate.d.ts +0 -69
  106. package/lambda-package/sanitizer/hitl-gate.d.ts.map +0 -1
  107. package/lambda-package/sanitizer/hitl-gate.js +0 -101
  108. package/lambda-package/sanitizer/hitl-gate.js.map +0 -1
  109. package/lambda-package/sanitizer/index.d.ts +0 -63
  110. package/lambda-package/sanitizer/index.d.ts.map +0 -1
  111. package/lambda-package/sanitizer/index.js +0 -105
  112. package/lambda-package/sanitizer/index.js.map +0 -1
  113. package/lambda-package/sanitizer/injection-detector.d.ts +0 -34
  114. package/lambda-package/sanitizer/injection-detector.d.ts.map +0 -1
  115. package/lambda-package/sanitizer/injection-detector.js +0 -89
  116. package/lambda-package/sanitizer/injection-detector.js.map +0 -1
  117. package/lambda-package/sanitizer/patterns.d.ts +0 -30
  118. package/lambda-package/sanitizer/patterns.d.ts.map +0 -1
  119. package/lambda-package/sanitizer/patterns.js +0 -372
  120. package/lambda-package/sanitizer/patterns.js.map +0 -1
  121. package/lambda-package/sanitizer/pii-allowlist.d.ts +0 -49
  122. package/lambda-package/sanitizer/pii-allowlist.d.ts.map +0 -1
  123. package/lambda-package/sanitizer/pii-allowlist.js +0 -231
  124. package/lambda-package/sanitizer/pii-allowlist.js.map +0 -1
  125. package/lambda-package/sanitizer/pii-redactor.d.ts +0 -41
  126. package/lambda-package/sanitizer/pii-redactor.d.ts.map +0 -1
  127. package/lambda-package/sanitizer/pii-redactor.js +0 -213
  128. package/lambda-package/sanitizer/pii-redactor.js.map +0 -1
  129. package/lambda-package/sanitizer/severity-classifier.d.ts +0 -33
  130. package/lambda-package/sanitizer/severity-classifier.d.ts.map +0 -1
  131. package/lambda-package/sanitizer/severity-classifier.js +0 -113
  132. package/lambda-package/sanitizer/severity-classifier.js.map +0 -1
  133. package/lambda-package/sanitizer/threat-reporter.d.ts +0 -66
  134. package/lambda-package/sanitizer/threat-reporter.d.ts.map +0 -1
  135. package/lambda-package/sanitizer/threat-reporter.js +0 -163
  136. package/lambda-package/sanitizer/threat-reporter.js.map +0 -1
  137. package/lambda-package/tools/fetch-structured.d.ts +0 -51
  138. package/lambda-package/tools/fetch-structured.d.ts.map +0 -1
  139. package/lambda-package/tools/fetch-structured.js +0 -237
  140. package/lambda-package/tools/fetch-structured.js.map +0 -1
  141. package/lambda-package/tools/fetch.d.ts +0 -49
  142. package/lambda-package/tools/fetch.d.ts.map +0 -1
  143. package/lambda-package/tools/fetch.js +0 -131
  144. package/lambda-package/tools/fetch.js.map +0 -1
  145. package/lambda-package/tools/read.d.ts +0 -51
  146. package/lambda-package/tools/read.d.ts.map +0 -1
  147. package/lambda-package/tools/read.js +0 -127
  148. package/lambda-package/tools/read.js.map +0 -1
  149. package/lambda-package/tools/search.d.ts +0 -45
  150. package/lambda-package/tools/search.d.ts.map +0 -1
  151. package/lambda-package/tools/search.js +0 -220
  152. package/lambda-package/tools/search.js.map +0 -1
  153. package/lambda-package/types.d.ts +0 -167
  154. package/lambda-package/types.d.ts.map +0 -1
  155. package/lambda-package/types.js +0 -16
  156. package/lambda-package/types.js.map +0 -1
  157. package/lambda-package/utils/format-converter.d.ts +0 -39
  158. package/lambda-package/utils/format-converter.d.ts.map +0 -1
  159. package/lambda-package/utils/format-converter.js +0 -191
  160. package/lambda-package/utils/format-converter.js.map +0 -1
  161. package/lambda-package/utils/truncate.d.ts +0 -26
  162. package/lambda-package/utils/truncate.d.ts.map +0 -1
  163. package/lambda-package/utils/truncate.js +0 -54
  164. package/lambda-package/utils/truncate.js.map +0 -1
  165. package/lambda.zip +0 -0
  166. package/test-output.txt +0 -4
  167. package/tests/auth-smoke.test.ts +0 -480
  168. package/tests/elicit-runner.test.ts +0 -232
  169. package/tests/fetch-tool.test.ts +0 -922
  170. package/tests/hitl-gate.test.ts +0 -267
  171. package/tests/injection-corpus.ts +0 -338
  172. package/tests/pii-allowlist.test.ts +0 -282
  173. package/tests/reader.test.ts +0 -353
  174. package/tests/sanitizer.test.ts +0 -358
  175. package/tests/search.test.ts +0 -456
  176. package/tests/threat-reporter.test.ts +0 -334
  177. package/tsconfig.cdk.json +0 -35
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-handler.js","sourceRoot":"","sources":["../../src/content-handlers/json-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,OAAwB,EACxB,QAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,qCAAqC;IACrC,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAElF,IAAI,CAAC;QACH,aAAa;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAEtC,gDAAgD;QAChD,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9C,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9C,MAAM,iBAAiB,GAA2D,EAAE,CAAC;QAErF,yCAAyC;QACzC,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;gBACzC,mBAAmB,EAAE,CAAC;YACxB,CAAC;YAED,qBAAqB;YACrB,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/E,MAAM,CAAC,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAChF,iBAAiB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;YAE/D,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,mCAAmC;QACnC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAEzD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAE9C,OAAO;YACL,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,QAAQ;YACtB,iBAAiB,EAAE,aAAa;YAChC,YAAY,EAAE;gBACZ,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBAClD,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBACnD,eAAe,EAAE,iBAAiB;gBAClC,gBAAgB,EAAE,mBAAmB;aACtC;YACD,kBAAkB,EAAE,cAAc;SACnC,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,2DAA2D;QAC3D,MAAM,kBAAkB,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QAEhD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAE9C,OAAO;YACL,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,QAAQ;YACtB,iBAAiB,EAAE,kBAAkB,CAAC,OAAO;YAC7C,YAAY,EAAE;gBACZ,iBAAiB,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB;gBACpE,kBAAkB,EAAE,kBAAkB,CAAC,YAAY,CAAC,kBAAkB;gBACtE,eAAe,EAAE,kBAAkB,CAAC,YAAY,CAAC,eAAe;gBAChE,gBAAgB,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB,CAAC,MAAM;aAC3E;YACD,kBAAkB,EAAE,cAAc;SACnC,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,GAAQ,EAAE,UAAoC;IACvE,cAAc;IACd,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8BAA8B;IAC9B,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,mDAAmD;IACnD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,kDAAkD;IAClD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAwB,EAAE,CAAC;QAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,YAAY,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,gEAAgE;IAChE,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * PDF Content Handler
3
+ *
4
+ * Handles application/pdf content type. Extracts text and metadata from PDF files,
5
+ * passes all text through the injection pattern registry, and returns sanitized plain text.
6
+ *
7
+ * What it handles:
8
+ * - PDF body text (full document)
9
+ * - PDF metadata: title, author, subject, keywords, creator, producer
10
+ * - Annotation text
11
+ * - Form field values
12
+ *
13
+ * What it strips:
14
+ * - Embedded binary objects (fonts, images, attachments)
15
+ * - Returns only extracted text, not original binary
16
+ *
17
+ * What it passes through:
18
+ * - All extracted text after injection pattern sanitization
19
+ */
20
+ import type { HandlerResult } from './types.js';
21
+ /**
22
+ * Handle PDF content
23
+ *
24
+ * @param content - Raw PDF binary data as Buffer or string
25
+ * @param mimeType - Original MIME type
26
+ * @returns Sanitized handler result
27
+ */
28
+ export declare function handlePdf(content: string | Buffer, mimeType: string): Promise<HandlerResult>;
29
+ //# sourceMappingURL=pdf-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf-handler.d.ts","sourceRoot":"","sources":["../../src/content-handlers/pdf-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAwDxB"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * PDF Content Handler
3
+ *
4
+ * Handles application/pdf content type. Extracts text and metadata from PDF files,
5
+ * passes all text through the injection pattern registry, and returns sanitized plain text.
6
+ *
7
+ * What it handles:
8
+ * - PDF body text (full document)
9
+ * - PDF metadata: title, author, subject, keywords, creator, producer
10
+ * - Annotation text
11
+ * - Form field values
12
+ *
13
+ * What it strips:
14
+ * - Embedded binary objects (fonts, images, attachments)
15
+ * - Returns only extracted text, not original binary
16
+ *
17
+ * What it passes through:
18
+ * - All extracted text after injection pattern sanitization
19
+ */
20
+ import { PDFParse } from 'pdf-parse';
21
+ import { sanitize } from '../sanitizer/index.js';
22
+ /**
23
+ * Handle PDF content
24
+ *
25
+ * @param content - Raw PDF binary data as Buffer or string
26
+ * @param mimeType - Original MIME type
27
+ * @returns Sanitized handler result
28
+ */
29
+ export async function handlePdf(content, mimeType) {
30
+ const startTime = Date.now();
31
+ try {
32
+ // Ensure we have a Buffer
33
+ const buffer = Buffer.isBuffer(content) ? content : Buffer.from(content);
34
+ // Parse PDF using pdf-parse v2 API
35
+ const parser = new PDFParse({ data: buffer });
36
+ // Get text and metadata separately
37
+ const textResult = await parser.getText();
38
+ const infoResult = await parser.getInfo();
39
+ // Extract text and metadata
40
+ const bodyText = textResult.text || '';
41
+ const metadata = infoResult.info || {};
42
+ // Build combined text from body + metadata
43
+ let combinedText = bodyText;
44
+ // Append metadata fields
45
+ const metadataFields = ['Title', 'Author', 'Subject', 'Keywords', 'Creator', 'Producer'];
46
+ for (const field of metadataFields) {
47
+ const value = metadata[field];
48
+ if (value && typeof value === 'string') {
49
+ combinedText += `\n\n${field}: ${value}`;
50
+ }
51
+ }
52
+ // Pass through injection detection pipeline
53
+ const sanitizationResult = sanitize(combinedText);
54
+ const processingTime = Date.now() - startTime;
55
+ return {
56
+ status: 'sanitized',
57
+ content_type: mimeType,
58
+ sanitized_content: sanitizationResult.content,
59
+ sanitization: {
60
+ patterns_detected: sanitizationResult.sanitization.patterns_detected,
61
+ pii_types_redacted: sanitizationResult.sanitization.pii_types_redacted,
62
+ pii_allowlisted: sanitizationResult.sanitization.pii_allowlisted,
63
+ sanitized_fields: sanitizationResult.sanitization.patterns_detected.length
64
+ },
65
+ processing_time_ms: processingTime
66
+ };
67
+ }
68
+ catch (error) {
69
+ return {
70
+ status: 'error',
71
+ reason: 'PDF_PARSE_FAILED',
72
+ mime: mimeType,
73
+ message: error instanceof Error ? error.message : String(error)
74
+ };
75
+ }
76
+ }
77
+ //# sourceMappingURL=pdf-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf-handler.js","sourceRoot":"","sources":["../../src/content-handlers/pdf-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAwB,EACxB,QAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,0BAA0B;QAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEzE,mCAAmC;QACnC,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAE9C,mCAAmC;QACnC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QAE1C,4BAA4B;QAC5B,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC;QAEvC,2CAA2C;QAC3C,IAAI,YAAY,GAAG,QAAQ,CAAC;QAE5B,yBAAyB;QACzB,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACzF,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC9B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvC,YAAY,IAAI,OAAO,KAAK,KAAK,KAAK,EAAE,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,4CAA4C;QAC5C,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QAElD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAE9C,OAAO;YACL,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,QAAQ;YACtB,iBAAiB,EAAE,kBAAkB,CAAC,OAAO;YAC7C,YAAY,EAAE;gBACZ,iBAAiB,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB;gBACpE,kBAAkB,EAAE,kBAAkB,CAAC,YAAY,CAAC,kBAAkB;gBACtE,eAAe,EAAE,kBAAkB,CAAC,YAAY,CAAC,eAAe;gBAChE,gBAAgB,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB,CAAC,MAAM;aAC3E;YACD,kBAAkB,EAAE,cAAc;SACnC,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,kBAAkB;YAC1B,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * SVG Content Handler
3
+ *
4
+ * Handles image/svg+xml content type. SVG is XML, not a binary image, and can contain
5
+ * executable code and external references. This handler strips dangerous elements and
6
+ * attributes unconditionally, then sanitizes remaining text content.
7
+ *
8
+ * What it handles:
9
+ * - All text content in SVG elements after stripping dangerous parts
10
+ *
11
+ * What it strips (unconditionally, no attempt to sanitize):
12
+ * - <script> elements and all children
13
+ * - <use> elements with external href or xlink:href attributes
14
+ * - <foreignObject> elements and all children
15
+ * - All event handler attributes (onload, onclick, onerror, etc.)
16
+ * - <set> and <animate> elements that reference external resources
17
+ * - data: URI attributes
18
+ *
19
+ * What it passes through (after injection scan):
20
+ * - Path data (d attribute)
21
+ * - Text elements and their content
22
+ * - <title> and <desc> elements
23
+ * - Presentation attributes (fill, stroke, transform, etc.)
24
+ * - viewBox, width, height attributes
25
+ */
26
+ import type { HandlerResult } from './types.js';
27
+ /**
28
+ * Handle SVG content
29
+ *
30
+ * @param content - Raw SVG XML string or Buffer
31
+ * @param mimeType - Original MIME type
32
+ * @returns Sanitized handler result
33
+ */
34
+ export declare function handleSvg(content: string | Buffer, mimeType: string): HandlerResult;
35
+ //# sourceMappingURL=svg-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg-handler.d.ts","sourceRoot":"","sources":["../../src/content-handlers/svg-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,aAAa,CAsEf"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * SVG Content Handler
3
+ *
4
+ * Handles image/svg+xml content type. SVG is XML, not a binary image, and can contain
5
+ * executable code and external references. This handler strips dangerous elements and
6
+ * attributes unconditionally, then sanitizes remaining text content.
7
+ *
8
+ * What it handles:
9
+ * - All text content in SVG elements after stripping dangerous parts
10
+ *
11
+ * What it strips (unconditionally, no attempt to sanitize):
12
+ * - <script> elements and all children
13
+ * - <use> elements with external href or xlink:href attributes
14
+ * - <foreignObject> elements and all children
15
+ * - All event handler attributes (onload, onclick, onerror, etc.)
16
+ * - <set> and <animate> elements that reference external resources
17
+ * - data: URI attributes
18
+ *
19
+ * What it passes through (after injection scan):
20
+ * - Path data (d attribute)
21
+ * - Text elements and their content
22
+ * - <title> and <desc> elements
23
+ * - Presentation attributes (fill, stroke, transform, etc.)
24
+ * - viewBox, width, height attributes
25
+ */
26
+ import { XMLParser, XMLBuilder } from 'fast-xml-parser';
27
+ import { sanitize } from '../sanitizer/index.js';
28
+ /**
29
+ * Handle SVG content
30
+ *
31
+ * @param content - Raw SVG XML string or Buffer
32
+ * @param mimeType - Original MIME type
33
+ * @returns Sanitized handler result
34
+ */
35
+ export function handleSvg(content, mimeType) {
36
+ const startTime = Date.now();
37
+ // Convert Buffer to string if needed
38
+ const svgString = Buffer.isBuffer(content) ? content.toString('utf-8') : content;
39
+ try {
40
+ // Parse SVG XML
41
+ const parser = new XMLParser({
42
+ ignoreAttributes: false,
43
+ attributeNamePrefix: '@_',
44
+ textNodeName: '#text',
45
+ preserveOrder: false,
46
+ removeNSPrefix: true,
47
+ });
48
+ const parsed = parser.parse(svgString);
49
+ // Track sanitized field count
50
+ let sanitizedFieldCount = 0;
51
+ // Strip dangerous elements and attributes
52
+ const stripped = stripDangerousContent(parsed);
53
+ // Extract all text content for injection scanning
54
+ const textContent = extractTextContent(stripped);
55
+ // Run text through injection detection
56
+ let sanitizationResult;
57
+ if (textContent.length > 0) {
58
+ sanitizationResult = sanitize(textContent);
59
+ if (sanitizationResult.sanitization.content_modified) {
60
+ sanitizedFieldCount = sanitizationResult.sanitization.patterns_detected.length;
61
+ }
62
+ }
63
+ // Rebuild SVG
64
+ const builder = new XMLBuilder({
65
+ ignoreAttributes: false,
66
+ attributeNamePrefix: '@_',
67
+ textNodeName: '#text',
68
+ format: true,
69
+ suppressEmptyNode: true,
70
+ });
71
+ const sanitizedSvg = builder.build(stripped);
72
+ const processingTime = Date.now() - startTime;
73
+ return {
74
+ status: 'sanitized',
75
+ content_type: mimeType,
76
+ sanitized_content: sanitizedSvg,
77
+ sanitization: {
78
+ patterns_detected: sanitizationResult?.sanitization.patterns_detected || [],
79
+ pii_types_redacted: sanitizationResult?.sanitization.pii_types_redacted || [],
80
+ pii_allowlisted: sanitizationResult?.sanitization.pii_allowlisted || [],
81
+ sanitized_fields: sanitizedFieldCount
82
+ },
83
+ processing_time_ms: processingTime
84
+ };
85
+ }
86
+ catch (error) {
87
+ return {
88
+ status: 'error',
89
+ reason: 'SVG_PARSE_FAILED',
90
+ mime: mimeType,
91
+ message: error instanceof Error ? error.message : String(error)
92
+ };
93
+ }
94
+ }
95
+ /**
96
+ * Strip dangerous content from parsed SVG
97
+ *
98
+ * Removes:
99
+ * - <script> elements
100
+ * - <foreignObject> elements
101
+ * - <use> with external href
102
+ * - Event handler attributes
103
+ * - <set> and <animate> with external references
104
+ * - data: URIs
105
+ */
106
+ function stripDangerousContent(node) {
107
+ if (typeof node !== 'object' || node === null) {
108
+ return node;
109
+ }
110
+ // Handle arrays
111
+ if (Array.isArray(node)) {
112
+ return node
113
+ .filter((item) => !shouldRemoveElement(item))
114
+ .map((item) => stripDangerousContent(item));
115
+ }
116
+ // Handle objects
117
+ const result = {};
118
+ for (const [key, value] of Object.entries(node)) {
119
+ // Skip dangerous elements
120
+ if (key === 'script' || key === 'foreignObject') {
121
+ continue;
122
+ }
123
+ // Handle <use> with external href
124
+ if (key === 'use' && typeof value === 'object' && value !== null) {
125
+ const href = value['@_href'] || value['@_xlink:href'];
126
+ if (href && (href.startsWith('http://') || href.startsWith('https://') || href.startsWith('//'))) {
127
+ continue;
128
+ }
129
+ }
130
+ // Handle <set> and <animate> with external references
131
+ if ((key === 'set' || key === 'animate') && typeof value === 'object' && value !== null) {
132
+ const href = value['@_href'] || value['@_xlink:href'];
133
+ if (href && (href.startsWith('http://') || href.startsWith('https://') || href.startsWith('//'))) {
134
+ continue;
135
+ }
136
+ }
137
+ // Strip event handler attributes
138
+ if (key.startsWith('@_on')) {
139
+ continue;
140
+ }
141
+ // Strip data: URIs
142
+ if (typeof value === 'string' && value.startsWith('data:')) {
143
+ result[key] = '';
144
+ continue;
145
+ }
146
+ // Strip attributes with data: URIs
147
+ if (key.startsWith('@_') && typeof value === 'string' && value.startsWith('data:')) {
148
+ continue;
149
+ }
150
+ // Recursively process
151
+ result[key] = stripDangerousContent(value);
152
+ }
153
+ return result;
154
+ }
155
+ /**
156
+ * Check if element should be removed entirely
157
+ */
158
+ function shouldRemoveElement(element) {
159
+ if (typeof element !== 'object' || element === null) {
160
+ return false;
161
+ }
162
+ // Check for dangerous element types
163
+ const dangerousElements = ['script', 'foreignObject'];
164
+ for (const dangerous of dangerousElements) {
165
+ if (dangerous in element) {
166
+ return true;
167
+ }
168
+ }
169
+ return false;
170
+ }
171
+ /**
172
+ * Extract all text content from SVG for injection scanning
173
+ */
174
+ function extractTextContent(node) {
175
+ if (typeof node !== 'object' || node === null) {
176
+ return '';
177
+ }
178
+ if (typeof node === 'string') {
179
+ return node;
180
+ }
181
+ if (Array.isArray(node)) {
182
+ return node.map((item) => extractTextContent(item)).join(' ');
183
+ }
184
+ let text = '';
185
+ for (const [key, value] of Object.entries(node)) {
186
+ // Extract text from text nodes
187
+ if (key === '#text' && typeof value === 'string') {
188
+ text += value + ' ';
189
+ }
190
+ // Extract from title and desc elements (can be string or object)
191
+ if (key === 'title' || key === 'desc') {
192
+ if (typeof value === 'string') {
193
+ text += value + ' ';
194
+ }
195
+ else if (typeof value === 'object') {
196
+ text += extractTextContent(value) + ' ';
197
+ }
198
+ }
199
+ // Recursively extract from other children
200
+ if (key !== 'title' && key !== 'desc' && typeof value === 'object') {
201
+ text += extractTextContent(value) + ' ';
202
+ }
203
+ }
204
+ return text.trim();
205
+ }
206
+ //# sourceMappingURL=svg-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg-handler.js","sourceRoot":"","sources":["../../src/content-handlers/svg-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Content Handler Types
3
+ *
4
+ * Shared interfaces for content-type specific handlers.
5
+ */
6
+ /**
7
+ * Success result from a content handler
8
+ */
9
+ export interface HandlerSuccessResult {
10
+ status: 'sanitized';
11
+ content_type: string;
12
+ sanitized_content: string;
13
+ sanitization: {
14
+ patterns_detected: string[];
15
+ pii_types_redacted: string[];
16
+ pii_allowlisted: Array<{
17
+ type: string;
18
+ value: string;
19
+ reason: string;
20
+ }>;
21
+ sanitized_fields: number;
22
+ };
23
+ processing_time_ms: number;
24
+ }
25
+ /**
26
+ * Error result from a content handler
27
+ */
28
+ export interface HandlerErrorResult {
29
+ status: 'error' | 'rejected';
30
+ reason: string;
31
+ mime: string;
32
+ message: string;
33
+ }
34
+ /**
35
+ * Union type for all handler results
36
+ */
37
+ export type HandlerResult = HandlerSuccessResult | HandlerErrorResult;
38
+ /**
39
+ * Content handler function signature
40
+ */
41
+ export type ContentHandler = (content: string | Buffer, mimeType: string) => Promise<HandlerResult> | HandlerResult;
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/content-handlers/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE;QACZ,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,eAAe,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACxE,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,GAAG,UAAU,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,kBAAkB,CAAC;AAEtE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Content Handler Types
3
+ *
4
+ * Shared interfaces for content-type specific handlers.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/content-handlers/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG7E;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAwFjG;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BpC,CAAC"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG7E;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAwJjG;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BpC,CAAC"}
@@ -9,6 +9,7 @@ import { renderPage } from '../browser/playwright-renderer.js';
9
9
  import { sanitize } from '../sanitizer/index.js';
10
10
  import { truncateContent } from '../utils/truncate.js';
11
11
  import { detectFormat, convertJson, convertXml, convertRss } from '../utils/format-converter.js';
12
+ import { routeContentHandler, normalizeMimeType } from '../content-handlers/index.js';
12
13
  import { Err } from '../types.js';
13
14
  /**
14
15
  * visus_fetch tool implementation
@@ -33,8 +34,65 @@ export async function visusFetch(input) {
33
34
  }
34
35
  const { html, title, contentType } = renderResult.value;
35
36
  const rawContent = html || '';
36
- // Step 2: Detect format and apply format-appropriate conversion
37
+ // Step 2: Detect content type and route to specialized handlers if applicable
37
38
  const detectedContentType = contentType || 'text/html';
39
+ const normalizedMime = normalizeMimeType(detectedContentType);
40
+ // Check if content requires specialized handler (PDF, JSON, SVG)
41
+ if (normalizedMime === 'application/pdf' ||
42
+ normalizedMime === 'application/json' ||
43
+ normalizedMime === 'text/json' ||
44
+ normalizedMime === 'image/svg+xml') {
45
+ // Route to specialized content handler
46
+ const handlerResult = await routeContentHandler(rawContent, detectedContentType);
47
+ // Handle unsupported or error cases
48
+ if (handlerResult.status === 'rejected' || handlerResult.status === 'error') {
49
+ return Err(new Error(handlerResult.message));
50
+ }
51
+ // Type guard: ensure we have a success result
52
+ if (handlerResult.status !== 'sanitized') {
53
+ return Err(new Error('Unexpected handler result status'));
54
+ }
55
+ // Handler success - use the already-sanitized content
56
+ const sanitizedContent = handlerResult.sanitized_content;
57
+ const sanitization = handlerResult.sanitization;
58
+ const truncationResult = truncateContent(sanitizedContent);
59
+ // Determine format_detected based on MIME type
60
+ let formatDetected = 'html';
61
+ if (normalizedMime === 'application/json' || normalizedMime === 'text/json') {
62
+ formatDetected = 'json';
63
+ }
64
+ else if (normalizedMime === 'image/svg+xml') {
65
+ formatDetected = 'xml'; // SVG is XML-based
66
+ }
67
+ else if (normalizedMime === 'application/pdf') {
68
+ // PDF doesn't have a format_detected value in the current schema
69
+ // Leaving as 'html' for now
70
+ }
71
+ const output = {
72
+ url,
73
+ content: truncationResult.content,
74
+ sanitization: {
75
+ patterns_detected: sanitization.patterns_detected,
76
+ pii_types_redacted: sanitization.pii_types_redacted,
77
+ pii_allowlisted: sanitization.pii_allowlisted,
78
+ content_modified: sanitization.sanitized_fields > 0
79
+ },
80
+ metadata: {
81
+ title: title || 'Untitled',
82
+ fetched_at: new Date().toISOString(),
83
+ content_length_original: rawContent.length,
84
+ content_length_sanitized: sanitizedContent.length,
85
+ format_detected: formatDetected,
86
+ content_type: detectedContentType,
87
+ ...(truncationResult.truncated && {
88
+ truncated: true,
89
+ truncated_at_chars: truncationResult.truncated_at_chars
90
+ })
91
+ }
92
+ };
93
+ return { ok: true, value: output };
94
+ }
95
+ // Step 3: For HTML/XML/RSS - use existing format conversion flow
38
96
  const formatType = detectFormat(detectedContentType);
39
97
  let processedContent = rawContent;
40
98
  // Apply format-specific conversion (skip Readability for non-HTML)
@@ -48,13 +106,13 @@ export async function visusFetch(input) {
48
106
  processedContent = convertRss(rawContent);
49
107
  }
50
108
  // For 'html' format, processedContent remains as rawContent
51
- // Step 3: CRITICAL - Sanitize content (injection detection + PII redaction with allowlisting)
109
+ // Step 4: CRITICAL - Sanitize content (injection detection + PII redaction with allowlisting)
52
110
  // This step CANNOT be skipped or bypassed
53
111
  const sanitizationResult = sanitize(processedContent, url);
54
- // Step 3: Apply token ceiling truncation (AFTER sanitization)
112
+ // Step 5: Apply token ceiling truncation (AFTER sanitization)
55
113
  // Anthropic MCP Directory enforces 25,000 token response limit
56
114
  const truncationResult = truncateContent(sanitizationResult.content);
57
- // Step 4: Build output
115
+ // Step 6: Build output
58
116
  const output = {
59
117
  url,
60
118
  content: truncationResult.content,
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtF,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,UAAU,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IAE/D,kBAAkB;IAClB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,CAAC;QACH,2CAA2C;QAC3C,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE;YACzC,UAAU;YACV,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU;SAChD,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;QAE9B,8EAA8E;QAC9E,MAAM,mBAAmB,GAAG,WAAW,IAAI,WAAW,CAAC;QACvD,MAAM,cAAc,GAAG,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;QAE9D,iEAAiE;QACjE,IAAI,cAAc,KAAK,iBAAiB;YACpC,cAAc,KAAK,kBAAkB;YACrC,cAAc,KAAK,WAAW;YAC9B,cAAc,KAAK,eAAe,EAAE,CAAC;YAEvC,uCAAuC;YACvC,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;YAEjF,oCAAoC;YACpC,IAAI,aAAa,CAAC,MAAM,KAAK,UAAU,IAAI,aAAa,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC5E,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/C,CAAC;YAED,8CAA8C;YAC9C,IAAI,aAAa,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACzC,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;YAC5D,CAAC;YAED,sDAAsD;YACtD,MAAM,gBAAgB,GAAG,aAAa,CAAC,iBAAiB,CAAC;YACzD,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;YAChD,MAAM,gBAAgB,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAAC;YAE3D,+CAA+C;YAC/C,IAAI,cAAc,GAAoC,MAAM,CAAC;YAC7D,IAAI,cAAc,KAAK,kBAAkB,IAAI,cAAc,KAAK,WAAW,EAAE,CAAC;gBAC5E,cAAc,GAAG,MAAM,CAAC;YAC1B,CAAC;iBAAM,IAAI,cAAc,KAAK,eAAe,EAAE,CAAC;gBAC9C,cAAc,GAAG,KAAK,CAAC,CAAC,mBAAmB;YAC7C,CAAC;iBAAM,IAAI,cAAc,KAAK,iBAAiB,EAAE,CAAC;gBAChD,iEAAiE;gBACjE,4BAA4B;YAC9B,CAAC;YAED,MAAM,MAAM,GAAqB;gBAC/B,GAAG;gBACH,OAAO,EAAE,gBAAgB,CAAC,OAAO;gBACjC,YAAY,EAAE;oBACZ,iBAAiB,EAAE,YAAY,CAAC,iBAAiB;oBACjD,kBAAkB,EAAE,YAAY,CAAC,kBAAkB;oBACnD,eAAe,EAAE,YAAY,CAAC,eAAe;oBAC7C,gBAAgB,EAAE,YAAY,CAAC,gBAAgB,GAAG,CAAC;iBACpD;gBACD,QAAQ,EAAE;oBACR,KAAK,EAAE,KAAK,IAAI,UAAU;oBAC1B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACpC,uBAAuB,EAAE,UAAU,CAAC,MAAM;oBAC1C,wBAAwB,EAAE,gBAAgB,CAAC,MAAM;oBACjD,eAAe,EAAE,cAAc;oBAC/B,YAAY,EAAE,mBAAmB;oBACjC,GAAG,CAAC,gBAAgB,CAAC,SAAS,IAAI;wBAChC,SAAS,EAAE,IAAI;wBACf,kBAAkB,EAAE,gBAAgB,CAAC,kBAAkB;qBACxD,CAAC;iBACH;aACF,CAAC;YAEF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACrC,CAAC;QAED,iEAAiE;QACjE,MAAM,UAAU,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;QAErD,IAAI,gBAAgB,GAAG,UAAU,CAAC;QAElC,mEAAmE;QACnE,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;YAC1B,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QAC7C,CAAC;aAAM,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;YAChC,gBAAgB,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC;aAAM,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;YAChC,gBAAgB,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC;QACD,4DAA4D;QAE5D,8FAA8F;QAC9F,0CAA0C;QAC1C,MAAM,kBAAkB,GAAG,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;QAE3D,8DAA8D;QAC9D,+DAA+D;QAC/D,MAAM,gBAAgB,GAAG,eAAe,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAErE,uBAAuB;QACvB,MAAM,MAAM,GAAqB;YAC/B,GAAG;YACH,OAAO,EAAE,gBAAgB,CAAC,OAAO;YACjC,YAAY,EAAE;gBACZ,iBAAiB,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB;gBACpE,kBAAkB,EAAE,kBAAkB,CAAC,YAAY,CAAC,kBAAkB;gBACtE,eAAe,EAAE,kBAAkB,CAAC,YAAY,CAAC,eAAe;gBAChE,gBAAgB,EAAE,kBAAkB,CAAC,YAAY,CAAC,gBAAgB;aACnE;YACD,QAAQ,EAAE;gBACR,KAAK,EAAE,KAAK,IAAI,UAAU;gBAC1B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,uBAAuB,EAAE,kBAAkB,CAAC,QAAQ,CAAC,eAAe;gBACpE,wBAAwB,EAAE,kBAAkB,CAAC,QAAQ,CAAC,gBAAgB;gBACtE,eAAe,EAAE,UAAU;gBAC3B,YAAY,EAAE,mBAAmB;gBACjC,GAAG,CAAC,gBAAgB,CAAC,SAAS,IAAI;oBAChC,SAAS,EAAE,IAAI;oBACf,kBAAkB,EAAE,gBAAgB,CAAC,kBAAkB;iBACxD,CAAC;aACH;YACD,+CAA+C;YAC/C,GAAG,CAAC,kBAAkB,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,kBAAkB,CAAC,aAAa,EAAE,CAAC;SAC7F,CAAC;QAEF,6CAA6C;QAC7C,IAAI,kBAAkB,CAAC,QAAQ,CAAC,oBAAoB,EAAE,CAAC;YACrD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,0BAA0B;gBACjC,GAAG;gBACH,QAAQ,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB;gBAC3D,cAAc,EAAE,kBAAkB,CAAC,QAAQ,CAAC,cAAc;aAC3D,CAAC,CAAC,CAAC;QACN,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAErC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,4BAA4B;IACnC,WAAW,EAAE,sSAAsS;IACnT,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gDAAgD;aAC9D;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;gBAC1B,WAAW,EAAE,iDAAiD;gBAC9D,OAAO,EAAE,UAAU;aACpB;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kDAAkD;gBAC/D,OAAO,EAAE,KAAK;aACf;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,CAAC;KAClB;IACD,YAAY,EAAE,IAAI;IAClB,eAAe,EAAE,KAAK;IACtB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,IAAI;CACpB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "visus-mcp",
3
- "version": "0.6.2",
3
+ "version": "0.8.0",
4
4
  "mcpName": "io.github.visus-mcp/visus-mcp",
5
5
  "description": "Security-first MCP server. Sanitizes web content before it reaches your LLM — strips prompt injection, redacts PII, and reduces token consumption by up to 70%.",
6
6
  "main": "dist/index.js",
@@ -48,6 +48,7 @@
48
48
  "cheerio": "^1.2.0",
49
49
  "fast-xml-parser": "^5.5.8",
50
50
  "jsdom": "^29.0.1",
51
+ "pdf-parse": "^2.4.5",
51
52
  "playwright": "^1.58.2",
52
53
  "undici": "^7.24.5"
53
54
  },
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/visus-mcp/visus-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.6.2",
9
+ "version": "0.8.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "visus-mcp",
14
- "version": "0.6.2",
14
+ "version": "0.8.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },