Skip to content

fix: MCP screenshot returns invalid base64 with puppeteer >=22#1

Merged
svincent240 merged 1 commit into
course-code-framework:mainfrom
Fieldnote-Echo:fix/mcp-screenshot-base64
Jul 20, 2026
Merged

fix: MCP screenshot returns invalid base64 with puppeteer >=22#1
svincent240 merged 1 commit into
course-code-framework:mainfrom
Fieldnote-Echo:fix/mcp-screenshot-base64

Conversation

@Fieldnote-Echo

Copy link
Copy Markdown
Contributor

Description

The coursecode_screenshot MCP tool fails on every call with MCP error -32602: Invalid tools/call result: ... "Invalid Base64 string", so MCP clients (Claude Code, Cursor, etc.) can never receive screenshots.

Root cause: page.screenshot() / elementHandle.screenshot() return a Uint8Array since Puppeteer v22 (this project pins puppeteer-core@^24.43.1). lib/headless-browser.js calls screenshotBuffer.toString('base64'), but Uint8Array.prototype.toString() ignores the encoding argument and returns comma-separated byte values ("255,216,255,..."), which then fails the MCP SDK's image-content validation.

Fix: wrap the result in Buffer.from(...) before encoding, which is correct whether Puppeteer returns a Buffer or a Uint8Array.

Repro

  1. coursecode create test-course && cd test-course && coursecode preview
  2. Start coursecode mcp and send over stdio:
    {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"coursecode_screenshot","arguments":{}}}
  3. Before: MCP error -32602 ... "Invalid Base64 string". After: valid base64 JPEG (/9j/4AAQSkZJRg...).

Related Issue

None filed — happy to open one first if you prefer issues for tracking.

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactoring
  • Other (describe):

Checklist

  • I have read the CONTRIBUTING guidelines
  • My code follows the project's code style
  • I have run npm run lint and it passes
  • I have tested my changes with npm run preview
  • I have updated documentation if needed (N/A — no user-facing behavior change beyond the fix)
  • My commits follow the conventional commit format

Testing

  • Full unit suite: 1340/1340 passing (npm test).
  • SCORM 1.2 and SCORM 2004 e2e driver suites: 14/14 each.
  • Manual verification against a live preview server via a raw MCP stdio client: coursecode_screenshot previously returned the -32602 validation error on every call; with this change it returns a valid image/jpeg content block (base64 starts with the JFIF magic /9j/). Also exercised coursecode_state, coursecode_navigate, and coursecode_lint in the same session to confirm no regressions in the MCP surface.

Screenshots (if applicable)

N/A (the fix is screenshots 🙂)

🤖 Generated with Claude Code

page.screenshot() returns Uint8Array since Puppeteer v22, and
Uint8Array.prototype.toString() ignores the 'base64' argument,
producing comma-separated byte values that fail MCP image content
validation ('Invalid Base64 string'). Wrap the result in Buffer.from()
so the base64 encoding applies regardless of the returned type.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@svincent240
svincent240 merged commit de47021 into course-code-framework:main Jul 20, 2026
2 checks passed
@svincent240

Copy link
Copy Markdown
Contributor

Thank you for the contribution! The fix looks good and is much appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants