Skip to main content
Glama
jameslupolt

Cookbook Shelf MCP

by jameslupolt

Cookbook Shelf

A small read-only Python CLI and MCP server for listing cookbooks on your Eat Your Books shelf and finding recipe references in those books.

Status: experimental; live CLI and MCP checks passed using regular Chrome attachment. Manually signing into a dedicated Chrome window, then connecting with EYB_CDP_URL, successfully listed the test account's full book inventory and searched its recipes across multiple pages. Version 0.2.1 also fixes Unicode output when a Windows CLI command is piped or redirected. There are 54 automated tests; see VALIDATION.md for the live checks and their limits.

The original Playwright-launched login still stalls on Cloudflare. The verified path is Attach to regular Chrome, below. An in-app browser login does not automatically sign this separate Chrome profile in.

Install

Requires Python 3.10+ and a supported desktop browser environment.

From this directory, with uv:

uv sync --extra mcp

Or with pip:

python -m pip install ".[mcp]"

After installation, follow Attach to regular Chrome below. Installed Google Chrome is sufficient for attachment; python -m playwright install chromium is only necessary for the original launcher mode. With uv, prefix cookbooks commands below with uv run.

In the original launcher mode (without EYB_CDP_URL), login opens a dedicated browser window. Sign in on EYB yourself, then press Enter in the terminal. Session cookies stay in that local browser profile. The tool does not ask for, log, or store your password in its configuration. It does not solve CAPTCHAs, use stealth plugins, or bypass access checks. If EYB blocks this browser, the tool reports that and stops; a browser-backed adapter is not guaranteed to avoid verification challenges.

Version 0.1.1 explicitly enables Chromium's sandbox, correcting the original launcher's --no-sandbox warning. This fixes a browser setting; it is not a Cloudflare fix. If verification stays on screen for about a minute, cancel in the terminal with Ctrl+C (or type q). If you press Enter while still challenged, the tool reports the block without making another navigation request. Cloudflare lists automated browsers as unsupported for production challenges.

Related MCP server: mcp-wikibooks-cookbook

Attach to regular Chrome (verified on the test account)

This option does not need a browser extension. Start Chrome yourself with a dedicated data directory and a local debugging port. On Windows, for example:

$env:EYB_PROFILE_DIR = Join-Path $env:LOCALAPPDATA 'cookbook-shelf\manual-chrome-profile'
$env:EYB_CDP_URL = 'http://127.0.0.1:9223'
$eybChrome = Join-Path $env:ProgramFiles 'Google\Chrome\Application\chrome.exe'
& $eybChrome "--user-data-dir=$env:EYB_PROFILE_DIR" --remote-debugging-address=127.0.0.1 --remote-debugging-port=9223 https://www.eatyourbooks.com/myhome

Sign in and reach your Bookshelf before running the CLI. Leave Chrome open. Use this dedicated profile only for EYB. The local debugging endpoint controls that browser; do not expose it on your network or use your everyday Chrome profile.

In the same terminal (after installing the package), run:

cookbooks --json login
cookbooks --json list
cookbooks --json search --ingredient edamame --max-pages 6

With EYB_CDP_URL set, login only verifies access; it never opens a sign-in form or asks for a password. Queries create and close their own temporary tab in the existing browser context. They do not close Chrome or the tab you used to sign in. --headed and EYB_BROWSER_CHANNEL apply only to launcher mode. --profile / EYB_PROFILE_DIR coordinates command locking in attachment mode; the attached browser itself determines the account and cookie profile.

You can also pass --cdp-url http://127.0.0.1:9223 before a CLI subcommand. Only HTTP endpoints at explicit loopback IP addresses and ports are accepted. MCP uses the same EYB_CDP_URL and EYB_PROFILE_DIR environment variables; the browser must already be open and signed in. No session credentials are copied. If a query is challenged, it stops. This is not a guarantee that EYB will accept automated searches after manual login.

Use

uv run cookbooks list
uv run cookbooks search --ingredient edamame
uv run cookbooks search --dish salsa
uv run cookbooks search --query '"Ina Garten" chicken'
uv run cookbooks --json search --ingredient edamame
uv run cookbooks --headed search --dish salsa

Global switches (--json, --headed, --profile, --cdp-url, --demo) go before the subcommand. Commands return exit code 2 for an actionable error and 130 on cancel.

  • Ingredient searches quote the phrase in EYB's search and then match it against listed ingredients. This avoids treating every broader soybean match as edamame. Use one ingredient phrase per query; for several ingredients use --query with EYB's normal search syntax. Synonyms are not silently invented.

  • Dish searches quote the phrase, then check titles and categories. Results may include "chicken with salsa" as well as standalone salsa recipes. This is candidate discovery, not exhaustive taxonomy classification.

  • Keyword passes the query to EYB and retains results whose source book ID is on your shelf. EYB supports exact phrases, exclusions, and title: queries.

  • Results preserve recipe and book links, authors, page numbers, ingredients, and categories when available. Unknown values stay null.

  • All searches first obtain your book inventory and restrict results to those IDs. Bookshelf navigation is used exclusively; there is no global-library fallback and no book, bookmark, or note mutation endpoint.

  • Book lists use the 200-entry condensed view. Recipe searches use the detailed view because condensed recipe lists omit ingredient metadata. On a mobile layout the parser also reads metadata beneath the expandable result.

  • Pagination follows EYB's next links, with a one-second minimum interval between navigation requests. It stops at limits, repeated pages, redirects to other searches, login pages, and verification/rate-limit responses. Where EYB displays a result count, the tool checks it against the records traversed before claiming completion.

Defaults: up to 500 books or 200 matching recipes, and 20 pages per listing. When limited, output explicitly says PARTIAL / truncated: true.

uv run cookbooks --json search --dish salsa --limit 1000 --max-pages 50

search_pages_complete means the returned EYB query pages were traversed. It does not mean that every physical book was fully searchable. Check indexing coverage and missing-metadata warnings. Unindexed books and incomplete indexes cannot supply all of their recipes. No quantities, methods, or dietary safety guarantees are inferred from index data.

Try without an account

uv run cookbooks --demo list
uv run cookbooks --demo search --ingredient edamame
uv run cookbooks --demo --json search --dish salsa

Demo content is fictional and labeled as such. Demo mode makes no network calls and does not start a browser.

MCP

The MCP interface uses the same service as the CLI. Two tools are exposed:

  • list_cookbooks(limit=500, max_pages=20)

  • search_my_recipes(query, mode="keyword", limit=200, max_pages=20)

Both are annotated read-only. No credentials are accepted as tool arguments. Login is performed separately in a terminal. Calls are serialized so the same profile cannot be driven concurrently. In attachment mode each operation closes only its own query tab and disconnects; Chrome remains open. In launcher mode it closes its browser. Protocol output uses stdout; browser/login issues are tool errors.

Example Codex configuration (replace the directory with this project's actual absolute path and use the same local OS account as cookbooks login):

[mcp_servers.cookbook_shelf]
command = "uv"
args = ["--directory", "/absolute/path/to/cookbook-shelf", "run", "--extra", "mcp", "cookbook-shelf-mcp"]
tool_timeout_sec = 180

[mcp_servers.cookbook_shelf.env]
EYB_CDP_URL = "http://127.0.0.1:9223"
EYB_PROFILE_DIR = "/absolute/path/to/dedicated-chrome-profile"

The local launcher does not need an OpenAI API key. Tool results are visible to the assistant and therefore to whichever model provider your MCP client uses.

Browser options

Environment variables are optional:

Variable

Purpose

EYB_PROFILE_DIR

Dedicated profile directory shared by login, CLI, and MCP

EYB_BROWSER_CHANNEL

chromium (default), chrome, or msedge

EYB_HEADED

Set to 1 to show the MCP query browser

EYB_DEMO

Set to 1 for the MCP server's fictional demonstration mode

EYB_CDP_URL

Attach to a dedicated, already-running local Chrome window

Do not point the tool at your normal browser profile. The default is %LOCALAPPDATA%/cookbook-shelf/browser-profile on Windows, the equivalent Application Support folder on macOS, or the XDG data folder on Linux. This profile contains session credentials. Keep it out of Git and shared folders. Use the same browser channel for login and subsequent queries.

Tests

uv sync --extra mcp --extra dev
uv run pytest

Tests exercise current-style mobile/condensed markup, recipe page numbers, ingredient matching, cookbook ownership, pagination, truncation, missing data, query encoding, expired sessions, verification pages, profile locking, CLI JSON, and MCP tool calls. They use synthetic fixtures rather than member data. See VALIDATION.md for the checks run and remaining limitations.

Origin and access terms

This implementation was written independently. The prior lampholder/eat-your-books wrapper was reviewed as a reference. It has no declared license and contains syntax errors, so none of its code was copied or vendored. The implementation also accounts for observed current differences: page numbers in recipe headings, metadata moved outside .book-data, and path-based pagination.

This project's MIT license covers our code, not EYB content or access rights. It is unaffiliated with Eat Your Books / CookShelf. EYB's terms restrict automated access and AI-related use; this implementation does not confer permission or resolve those restrictions. A user's normal browser session is an authentication mechanism, not an exemption. No database of EYB content is distributed here.

References: EYB search documentation, MCP Python SDK, Playwright Python.

Available Tools

2 tools
list_cookbooksB
Read-onlyIdempotent

List cookbooks on the user's EYB shelf and known indexing coverage. Bounded, read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
max_pagesNo

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotent, non-destructive, and open-world behavior. The description adds 'Bounded' (implying limits/pagination) and 'known indexing coverage' (signaling results reflect the current index), which are useful behavioral details beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the action front-loaded. Every word earns its place, and there is no redundant explanation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list tool with two optional, self-explanatory parameters and strong annotations, the description is nearly sufficient. It names the returned content ('cookbooks' and 'indexing coverage') but stops short of describing result shape or pagination behavior, and there is no output schema to fill that gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not explain limit or max_pages. 'Bounded' loosely hints at pagination/limits but does not clarify the parameters' meaning, defaults, or interaction, so the description fails to compensate for the sparse schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('List cookbooks on the user's EYB shelf') and adds the useful scope of 'known indexing coverage.' It clearly states what the tool does, but it does not explicitly differentiate itself from the sibling search_my_recipes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance is provided, and the sibling search_my_recipes is not mentioned. 'Bounded, read-only' describes constraints but does not help an agent decide between this tool and the alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_my_recipesA
Read-onlyIdempotent

Find recipe references only in cookbooks on the user's shelf. Ingredient mode checks listed ingredient phrases; dish mode checks title/category candidates and can include served-with dishes. Search is limited to EYB's indexed keyword candidates. Always check truncation and missing metadata.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNokeyword
limitNo
queryYes
max_pagesNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, the description reveals non-obvious behavior: it searches only EYB's indexed keyword candidates, dish mode can include served-with dishes, and results may suffer from truncation or missing metadata. These are exactly the behavioral caveats an agent needs to interpret results correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with the primary scope front-loaded. Each sentence adds a distinct necessary fact: scope, mode behavior, and search/caveat limitations. No filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does not specify return shape, yet it equips an agent with mode semantics, indexing constraints, and a truncation warning so it can validate results. It is slightly terse about pagination parameters and metadata caveats, but sufficient for a read-only search tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning. It explains the mode values and implies the query uses EYB-indexed candidates, but limit and max_pages are left to their names and defaults, so compensation is strong yet not complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action and resource: 'Find recipe references only in cookbooks on the user's shelf,' which clearly distinguishes this tool from sibling list_cookbooks. It also names each mode and what it checks, making the tool's scope concrete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operational context by explaining what each mode searches and warning about indexed-keyword limitations. However, it does not explicitly state when to prefer this tool over list_cookbooks or provide a when-not-to-use condition, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.2.1
    • First observedlist_cookbooks
    • First observedsearch_my_recipes

TDQS

A3.9/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have cleanly separated purposes: one inventories the shelf and indexing coverage, the other searches recipe references within it. There is no functional overlap between them.

Naming Consistency5/5

Both tools follow a snake_case verb_noun pattern: list_cookbooks and search_my_recipes. The 'my' qualifier in the second name is a minor modifier and does not break the overall convention.

Tool Count3/5

With only two tools, the server feels minimally scoped and sits at the thin boundary for a useful MCP surface. It is reasonable for a narrow read-only use case but may leave agents wanting more.

Completeness4/5

The tools cover the core read-only workflow: listing shelf coverage and searching for recipe references by ingredient or dish. Richer recipe detail or shelf management functionality is likely out of scope, though it could be a minor gap in some workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    A read-only MCP server for Mealie that enables searching recipes, managing shopping lists, meal plans, and retrieving household/instance info via tools. Supports secure per-user authentication and multiple Mealie instances.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Search and read recipes from the English Wikibooks Cookbook, with tools to rescale ingredient lists to a target number of servings.
    4
    156 npm
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables reading, searching, creating, and safely modifying Brewfather recipes via the Brewfather API, with local credential storage and confirmation-based writes.
    8
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables authenticated clients to search and read a private EPUB cookbook catalog, retrieve source-bound citations and selected images, and activate verified immutable publications.
    -