@sylphlab/tools-pdf
Version:
Core logic for MCP PDF tools (text extraction, etc.)
164 lines (160 loc) • 6.52 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
extractPdfText: () => extractPdfText,
getTextTool: () => getTextTool,
getTextToolInputSchema: () => getTextToolInputSchema
});
module.exports = __toCommonJS(index_exports);
// src/tools/getTextTool.ts
var import_promises = require("fs/promises");
var import_tools_core = require("@sylphlab/tools-core");
var import_tools_core2 = require("@sylphlab/tools-core");
var mupdfjs = __toESM(require("mupdf/mupdfjs"), 1);
var import_zod2 = require("zod");
// src/tools/getTextTool.schema.ts
var import_zod = require("zod");
var GetTextItemSchema = import_zod.z.object({
id: import_zod.z.string().optional(),
filePath: import_zod.z.string().min(1, "filePath cannot be empty.")
// Add options like page range later if needed
});
var getTextToolInputSchema = import_zod.z.object({
items: import_zod.z.array(GetTextItemSchema).min(1, "At least one PDF item is required.")
// allowOutsideWorkspace is handled by ToolExecuteOptions
});
// src/tools/getTextTool.ts
var import_tools_core3 = require("@sylphlab/tools-core");
async function extractPdfText(pdfBuffer) {
let doc;
try {
doc = mupdfjs.PDFDocument.openDocument(pdfBuffer, "application/pdf");
const numPages = doc.countPages();
const pageTexts = [];
for (let i = 0; i < numPages; i++) {
let page;
try {
page = doc.loadPage(i);
pageTexts.push(page.getText());
} finally {
page?.destroy();
}
}
return pageTexts.join("\n").trim();
} finally {
doc?.destroy();
}
}
var GetTextResultItemSchema = import_zod2.z.object({
id: import_zod2.z.string().optional(),
path: import_zod2.z.string(),
// Added path to result schema
success: import_zod2.z.boolean(),
result: import_zod2.z.string().optional(),
error: import_zod2.z.string().optional(),
suggestion: import_zod2.z.string().optional()
});
var GetTextToolOutputSchema = import_zod2.z.array(GetTextResultItemSchema);
async function processSinglePdfGetText(item, options) {
const { id, filePath: inputFilePath } = item;
const resultItem = { id, path: inputFilePath, success: false };
const { workspaceRoot, allowOutsideWorkspace } = options;
let resolvedPath;
try {
const validationResult = (0, import_tools_core2.validateAndResolvePath)(
inputFilePath,
workspaceRoot,
allowOutsideWorkspace
);
if (typeof validationResult !== "string") {
throw new Error(
`Path validation failed: ${validationResult.error} ${validationResult.suggestion ?? ""}`
);
}
resolvedPath = validationResult;
const buffer = await (0, import_promises.readFile)(resolvedPath);
const extractedText = await extractPdfText(buffer);
resultItem.success = true;
resultItem.result = extractedText;
resultItem.suggestion = "Successfully extracted text from PDF.";
} catch (e) {
resultItem.success = false;
const errorMsg = e instanceof Error ? e.message : String(e);
resultItem.error = `Failed to get text from PDF '${inputFilePath}': ${errorMsg}`;
if (errorMsg.includes("Path validation failed")) {
resultItem.suggestion = errorMsg.split("Suggestion: ")[1] ?? "Check path validity and workspace settings.";
} else if (e && typeof e === "object" && "code" in e) {
if (e.code === "ENOENT") {
resultItem.suggestion = "Ensure the file path is correct and the file exists.";
} else if (e.code === "EACCES") {
resultItem.suggestion = "Check file read permissions.";
} else {
resultItem.suggestion = "Ensure the file is a valid, uncorrupted PDF and check permissions.";
}
} else if (errorMsg.toLowerCase().includes("pdf")) {
resultItem.suggestion = "Ensure the file is a valid, uncorrupted PDF document.";
} else {
resultItem.suggestion = "Check file path, permissions, and file validity.";
}
}
return resultItem;
}
var getTextTool = (0, import_tools_core.defineTool)({
name: "get-text",
description: "Extracts text content from one or more PDF files.",
inputSchema: getTextToolInputSchema,
contextSchema: import_tools_core3.BaseContextSchema,
// Add context schema
execute: async ({ context, args }) => {
const parsed = getTextToolInputSchema.safeParse(args);
if (!parsed.success) {
const errorMessages = Object.entries(parsed.error.flatten().fieldErrors).map(([field, messages]) => `${field}: ${messages.join(", ")}`).join("; ");
throw new Error(`Input validation failed: ${errorMessages}`);
}
if (!context?.workspaceRoot) {
throw new Error("Workspace root is not available in context.");
}
const { items } = parsed.data;
const results = [];
for (const item of items) {
const result = await processSinglePdfGetText(item, context);
results.push(result);
}
return [(0, import_tools_core2.jsonPart)(results, GetTextToolOutputSchema)];
}
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
extractPdfText,
getTextTool,
getTextToolInputSchema
});
//# sourceMappingURL=index.cjs.map