Skip to main content
Glama
steveclarke

MCP Printer Server

by steveclarke

get_page_meta

Analyze files to determine page count and physical sheet requirements before printing. Pre-renders documents when necessary to provide accurate printing metadata.

Instructions

Get page count and physical sheet information for a file before printing. Pre-renders the file (if needed) and returns page metadata including page count and physical sheets required.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filesYesArray of files to get metadata for (use single-element array for one file)

Implementation Reference

  • Registration of the 'get_page_meta' tool with MCP server, including input schema and batch handler that delegates to handlePageMeta
    server.registerTool(
      "get_page_meta",
      {
        title: "Get Page Metadata",
        description:
          "Get page count and physical sheet information for a file before printing. Pre-renders the file (if needed) and returns page metadata including page count and physical sheets required.",
        inputSchema: {
          files: z
            .array(
              z.object({
                file_path: z.string().describe("Full path to the file to get page metadata for"),
                options: z
                  .string()
                  .optional()
                  .describe(
                    "Additional CUPS options for duplex detection (e.g., 'sides=two-sided-long-edge')"
                  ),
                ...renderingParametersSchema,
              })
            )
            .describe("Array of files to get metadata for (use single-element array for one file)"),
        },
      },
      async ({ files }) => {
        // Check for large batch size
        const batchSizeWarning = checkBatchSizeLimit(files.length, "files")
        if (batchSizeWarning) {
          return batchSizeWarning
        }
    
        // Process each file in the batch
        const results: PageMetaResult[] = []
        for (const fileSpec of files) {
          const result = await handlePageMeta(fileSpec)
          results.push(result)
        }
    
        return formatPageMetaResults(results)
      }
    )
  • Core handler function that implements the get_page_meta tool logic: prepares/renders file, extracts PDF page count, calculates physical sheets considering duplex, handles errors and cleanup.
    export async function handlePageMeta(spec: FilePageMetaSpec): Promise<PageMetaResult> {
      const {
        file_path,
        options,
        line_numbers,
        color_scheme,
        font_size,
        line_spacing,
        force_markdown_render,
        force_code_render,
      } = spec
    
      try {
        // Use shared rendering function
        const { actualFilePath, renderedPdf, renderType } = await prepareFileForPrinting({
          filePath: file_path,
          lineNumbers: line_numbers,
          colorScheme: color_scheme,
          fontSize: font_size,
          lineSpacing: line_spacing,
          forceMarkdownRender: force_markdown_render,
          forceCodeRender: force_code_render,
        })
    
        try {
          // Get page count from the file
          const pdfPages = await getPdfPageCount(actualFilePath)
          const isDuplex = isDuplexEnabled(options)
          const physicalSheets = calculatePhysicalSheets(pdfPages, isDuplex)
    
          return {
            success: true,
            file_path,
            pages: pdfPages,
            sheets: physicalSheets,
            duplex: isDuplex,
            renderType,
          }
        } finally {
          // Clean up rendered PDF if it was created
          cleanupRenderedPdf(renderedPdf)
        }
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error)
        return {
          success: false,
          file_path,
          error: `Failed to get page metadata: ${message}`,
        }
      }
    }
  • Shared Zod schema for rendering parameters used in inputSchema for both print_file and get_page_meta tools.
    const renderingParametersSchema = {
      line_numbers: z
        .boolean()
        .optional()
        .describe("Show line numbers when rendering code files (overrides global setting)"),
      color_scheme: z
        .string()
        .optional()
        .describe(
          "Syntax highlighting color scheme for code files (e.g., 'github', 'monokai', 'atom-one-light')"
        ),
      font_size: z
        .string()
        .optional()
        .describe("Font size for code files (e.g., '8pt', '10pt', '12pt')"),
      line_spacing: z
        .string()
        .optional()
        .describe("Line spacing for code files (e.g., '1', '1.5', '2')"),
      force_markdown_render: z
        .boolean()
        .optional()
        .describe(
          "Force markdown rendering to PDF (true=always render, false=never render, undefined=use config)"
        ),
      force_code_render: z
        .boolean()
        .optional()
        .describe(
          "Force code rendering to PDF with syntax highlighting (true=always render, false=never render, undefined=use config)"
        ),
    }
  • Formats the batch results from handlePageMeta into a readable MCP text response.
    export function formatPageMetaResults(results: PageMetaResult[]): {
      content: Array<{ type: "text"; text: string }>
    } {
      const successful = results.filter((r) => r.success)
      const failed = results.filter((r) => !r.success)
    
      let text = `Page Metadata Results: ${successful.length}/${results.length} successful`
      if (failed.length > 0) {
        text += `, ${failed.length} failed`
      }
      text += "\n\n"
    
      // Show successful metadata
      for (const result of successful) {
        text += `✓ ${result.file_path}\n  ${result.pages} pages (${result.sheets} sheets${formatDuplexInfo(result.duplex)})${formatRenderInfo(result.renderType)}\n\n`
      }
    
      // Show failed metadata
      for (const result of failed) {
        text += `✗ ${result.file_path}\n  ${result.error}\n\n`
      }
    
      return {
        content: [
          {
            type: "text",
            text: text.trim(),
          },
        ],
      }
    }
  • Core utility function that prepares files for printing by rendering markdown/code to PDF if needed. Used by both print_file and get_page_meta tools.
    export async function prepareFileForPrinting(options: RenderOptions): Promise<RenderResult> {
      // Validate file path security
      validateFilePath(options.filePath)
    
      let actualFilePath = options.filePath
      let renderedPdf: string | null = null
      let renderType = ""
    
      // Check if file should be auto-rendered to PDF (markdown)
      const shouldRenderMarkdown =
        options.forceMarkdownRender !== undefined
          ? options.forceMarkdownRender &&
            MARKDOWN_EXTENSIONS.some((ext) => options.filePath.toLowerCase().endsWith(`.${ext}`))
          : shouldRenderToPdf(options.filePath)
    
      if (shouldRenderMarkdown) {
        try {
          renderedPdf = await renderMarkdownToPdf(options.filePath)
          actualFilePath = renderedPdf
          renderType = "markdown → PDF"
        } catch (error) {
          // If fallback is enabled, use original file; otherwise throw error
          if (config.fallbackOnRenderError) {
            console.error(`Warning: Failed to render ${options.filePath}, using as-is:`, error)
          } else {
            throw error
          }
        }
      }
      // Check if file should be rendered as code with syntax highlighting
      else if (
        options.forceCodeRender !== undefined
          ? options.forceCodeRender
          : await shouldRenderCode(options.filePath)
      ) {
        try {
          renderedPdf = await renderCodeToPdf(options.filePath, {
            lineNumbers: options.lineNumbers,
            colorScheme: options.colorScheme,
            fontSize: options.fontSize,
            lineSpacing: options.lineSpacing,
          })
          actualFilePath = renderedPdf
          renderType = "code → PDF (syntax highlighted)"
        } catch (error) {
          // If fallback is enabled, use original file; otherwise throw error
          if (config.fallbackOnRenderError) {
            console.error(`Warning: Failed to render code ${options.filePath}, using as-is:`, error)
          } else {
            throw error
          }
        }
      }
    
      return { actualFilePath, renderedPdf, renderType }
    }

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/steveclarke/mcp-printer'

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