Skip to main content
Glama

pdf_embed_qr_code

Add QR codes or barcodes to PDF pages at precise positions to encode data like URLs, contact details, or product information directly into documents.

Instructions

Embed a QR code or barcode into a specific page of a PDF at given coordinates. Supports qrcode, code128, datamatrix, ean13, pdf417, and azteccode.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filePathYesAbsolute path to the source PDF file
contentYesData to encode in the QR code or barcode
outputPathYesAbsolute path for the output PDF
pageYesTarget page number (1-indexed)
xYesX position in points from the left edge
yYesY position in points from the bottom edge
sizeNoSize of the QR code/barcode in points. Defaults to 100.
typeNoBarcode type. Defaults to qrcode.

Implementation Reference

  • The tool `pdf_embed_qr_code` is defined and implemented in `src/tools/manipulate.ts`. It registers the tool with the MCP server, defines its input schema using `zod`, and handles the logic for generating a barcode (using `bwip-js`) and embedding it into a specified page of a PDF using `pdf-lib`.
    // ── pdf_embed_qr_code ───────────────────────────────────────────────
    server.registerTool(
      "pdf_embed_qr_code",
      {
        description:
          "Embed a QR code or barcode into a specific page of a PDF at given coordinates. Supports qrcode, code128, datamatrix, ean13, pdf417, and azteccode.",
        inputSchema: z
          .object({
            filePath: z
              .string()
              .max(4096)
              .describe("Absolute path to the source PDF file"),
            content: z
              .string()
              .min(1)
              .max(4096)
              .describe("Data to encode in the QR code or barcode"),
            outputPath: z
              .string()
              .max(4096)
              .describe("Absolute path for the output PDF"),
            page: z
              .number()
              .int()
              .min(1)
              .describe("Target page number (1-indexed)"),
            x: z
              .number()
              .describe("X position in points from the left edge"),
            y: z
              .number()
              .describe("Y position in points from the bottom edge"),
            size: z
              .number()
              .min(10)
              .max(1000)
              .optional()
              .describe("Size of the QR code/barcode in points. Defaults to 100."),
            type: z
              .enum(["qrcode", "code128", "datamatrix", "ean13", "pdf417", "azteccode"])
              .optional()
              .describe("Barcode type. Defaults to qrcode."),
          })
          .strict(),
        annotations: {
          readOnlyHint: false,
          destructiveHint: false,
          idempotentHint: true,
          openWorldHint: false,
        },
      },
      async ({ filePath, content, outputPath, page, x, y, size, type }) => {
        try {
          const resolvedPath = await validatePdfPath(filePath);
          await validateFileSize(resolvedPath);
          const resolvedOutput = await validateOutputPath(outputPath, filePath);
    
          const barcodeType = type ?? "qrcode";
          const barcodeSize = size ?? 100;
    
          // Generate barcode as PNG buffer
          const pngBuffer = await bwipToBuffer({
            bcid: barcodeType,
            text: content,
            scale: 3,
            includetext: false,
          });
    
          const pdfDoc = await loadExistingPdf(resolvedPath);
          const totalPages = pdfDoc.getPageCount();
    
          if (page > totalPages) {
            return toolError(
              `Page ${page} exceeds document length (${totalPages} pages).`
            );
          }
    
          const image = await pdfDoc.embedPng(pngBuffer);
          const targetPage = pdfDoc.getPage(page - 1);
    
          targetPage.drawImage(image, {
            x,
            y,
            width: barcodeSize,
            height: barcodeSize,
          });
    
          await savePdf(pdfDoc, resolvedOutput);
          const fileSize = await getFileSize(resolvedOutput);
    
          return toolSuccess({
            outputPath: resolvedOutput,
            page,
            type: barcodeType,
            position: { x, y },
            size: barcodeSize,
            fileSize,
          });
        } catch (error) {
          return toolError(
            error instanceof Error ? error.message : String(error)
          );
        }
      }
    );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AryanBV/pdf-toolkit-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server