Skip to content

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

vitalsource-mcp

An MCP server that drives VitalSource Bookshelf through a real Chromium browser via Playwright. It exposes tools, resources, and a prompt so an agent (e.g. Claude Code) can list your books, read chapter text, and save notes — all against textbooks you already own through VitalSource.

There is no public VitalSource API for personal libraries, so this works by automating the web reader. Selectors live in one file (src/vitalsource/selectors.ts) and may need patching if VitalSource ships a UI change.


Disclaimer — read before using

This project is for personal and educational use only. It is not affiliated with, endorsed by, or in any way connected to VitalSource Technologies. Automating a browser against a paid subscription service may violate VitalSource's Terms of Service. You use this software entirely at your own risk.


Install

Requires Node 20+.

npm install
npx playwright install chromium   # one-time — Playwright needs its own Chromium
npm run build

First-run login

The first time you use the server you need to sign in interactively so the session is persisted to disk:

  1. Have your MCP client call the login tool (or call it without arguments; it defaults to auto mode).
  2. A visible Chromium window opens and navigates to the VitalSource login page.
  3. Sign in normally — Google/Apple SSO and two-factor auth all work because you are driving a real browser.
  4. The window closes automatically once you reach the library shelf. The session is written to user-data/auth-state.json.

Subsequent tool calls reuse the persisted session and run headless. If the session expires, call login again.

Headless / unattended login

If your VitalSource account uses a native email + password (no SSO, no 2FA), you can set credentials in the server environment:

VS_MCP_EMAIL=you@example.com
VS_MCP_PASSWORD=your_password

When both are set, ensureLoggedIn() signs in automatically without opening a window. This mode does not work for accounts that use Google, Apple, or institution SSO — use the interactive flow instead.

Tools

Every tool returns both a text content block and a structuredContent object.

Tool Inputs Structured output
login mode? ("auto" | "credential" | "interactive", default "auto") { status: string, mode: "credential" | "interactive" }
list_books — { books: [{ bookId, title, edition, href }] }
get_toc bookId { bookId, entries: [{ chapterId, title, page }] }
read_chapter bookId, chapterId, format? ("md" | "text", default "md"), maxPages? (int, max 1000), maxChars? (int, max 1 000 000) { bookId, chapterId, pageCount, charCount, truncated, content }
save_notes filename, content, subdir?, book?, chapter? { path, bytes }

login — "auto" mode uses credential login when VS_MCP_EMAIL + VS_MCP_PASSWORD are set, otherwise falls back to interactive. Pass "credential" or "interactive" to force a mode.

get_toc — chapterId is a tocIndexN uuid (e.g. "tocIndex9"), not a CFI. This same id is what read_chapter expects.

read_chapter — navigates to the chapter and walks its pages via ArrowRight. maxPages caps how many page turns are attempted (default 200). maxChars caps the returned text (default 100 000 chars). truncated is true if either limit was hit.

save_notes — writes a UTF-8 markdown file under the notes root (default <project>/notes/). book and chapter are added to YAML frontmatter if provided. subdir is restricted to inside the notes root; path traversal is rejected.

Resources

Resources expose the same data as tools, usable without explicit tool calls.

URI MIME type Returns
vitalsource://library application/json Full book list (same shape as list_books)
vitalsource://book/{bookId}/toc application/json TOC entries for the given book
vitalsource://book/{bookId}/chapter/{chapterId} text/markdown Chapter content as Markdown

Prompt

study_notes(book, chapter) — generates a user-role prompt message that instructs the agent to call list_books → get_toc → read_chapter in sequence, then write lean cheat-sheet-style notes (flat #### headings, bold-label bullets) and optionally save them with save_notes.

Register with Claude Code

claude mcp add-json vitalsource '{"command":"node","args":["C:\\vitalsource-mcp\\dist\\index.js"]}'

Using add-json is more reliable on Windows than the -- node ... form because it avoids shell argument-splitting issues.

For development without a build step:

claude mcp add-json vitalsource '{"command":"npx","args":["tsx","C:\\vitalsource-mcp\\src\\index.ts"]}'

A typical agent flow looks like:

"Take notes on chapter 2 of Linear Algebra Done Right."

The agent chains list_books → get_toc → read_chapter → drafts notes → save_notes.

Known limitations

  • DRM / image-only books. Some titles disable text extraction or are scan-only. Chapter content comes back empty or as garbled markup. No workaround short of OCR.
  • Selector drift. All CSS selectors and URL patterns live in src/vitalsource/selectors.ts. When a tool returns empty results after a Bookshelf update, that file is the first place to look. Each selector is a comma-joined fallback chain in priority order; bump the "Last verified" date in the header when you revalidate.
  • Single browser context / serialized calls. All tool calls share one BrowserContext. runExclusive queues them so they do not run in true parallel. Two simultaneous read_chapter calls will execute back-to-back, not concurrently.
  • Interactive login needs a desktop. The headed browser window cannot open on a headless server with no display. Use credential mode (VS_MCP_EMAIL / VS_MCP_PASSWORD) for unattended environments — but only if your account is a native email + password account.
  • First-open cold load. A book that has never been opened in this browser profile must download assets on first access. waitForToc retries once after a reload; the whole sequence can take up to ~90 seconds.

Configuration

Variable Default Purpose
VS_MCP_USER_DATA_DIR <project>/user-data Where Playwright persists the browser profile.
VS_MCP_NOTES_DIR <project>/notes Where save_notes writes markdown files.
VS_MCP_EMAIL — Email for headless credential login.
VS_MCP_PASSWORD — Password for headless credential login. Native accounts only — not SSO.

Development

npm run dev        # run MCP server from source via tsx (speaks stdio — attach an MCP client)
npm test           # Vitest unit tests (pure-function coverage; browser paths verified manually)
npm run typecheck  # tsc --noEmit
npm run prettier:fix

Project layout

src/
  index.ts                  MCP entry: registers 5 tools, 3 resources, 1 prompt; connects stdio
  config.ts                 paths + env overrides
  browser.ts                BrowserManager singleton (persistent context + runExclusive mutex)
  notes.ts                  saveNotes() — sanitized filename/subdir, YAML frontmatter, isInside guard
  vitalsource/
    selectors.ts            all CSS selectors + URL builders (single source of truth)
    auth.ts                 ensureLoggedIn(), interactiveLogin(), credentialLogin()
    library.ts              listBooks()
    toc.ts                  getToc(bookId)
    reader.ts               readChapter() — iframe discovery, page-turn loop, boundContent
    page-helpers.ts         waitForToc() — cold-load retry helper

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages