databasedmcp

← Articles

How to build a reading log with Grok

Keep a list of what you want to read, what you're reading and what you thought of it, by telling Grok.

6 min read

databasedmcp gives your AI assistant databases it keeps between conversations, so everything in this article works from the day you connect it. Free to start, no card.

Get started free

Why build it yourself

Goodreads and StoryGraph are where many readers keep their shelves: what they want to read, what they're on, what they finished and what they thought. If you mostly use them as a private log, the log is a table you can own.

Tell Grok you started a book, where you are in it, and what you made of it when you finish. It keeps the dates and the ratings. It answers "how many pages did I read this year?" or "something short from my list" from your own data.

Connect Grok to databasedmcp

databasedmcp is a remote MCP server that gives AI assistants private SQLite databases, with nothing to install.

Open grok.com/connectors, add a new connector, choose Custom and enter https://databasedmcp.com/mcp. When Grok opens the databasedmcp page, sign in and select Allow. Then turn the connector on in a chat.

Any other MCP client works the same way; the docs have the details.

Copy this prompt to build it

Paste this into Grok to set up the database, its tables and its guide in one go. The rest of this article walks through what it makes and how you use it.

prompt
Set up a reading log for me in databasedmcp, in one go.

1. Create a database called reading, described as "Reading log: books I want to read, am reading and have finished, with ratings, notes and progress, filed by Grok".
2. Create two tables:
   - books: id, title (required), author (required), pages, tags (a JSON array of lowercase strings like ["fiction", "sci-fi"], defaults to []), status (want, reading, finished or abandoned, defaults to want), started_on (date), finished_on (date), rating (1 to 5), notes (what I thought, in my words), added_at (defaults to now).
   - progress: id, book_id (references books), on_day (date, defaults to today), page (required).
3. Write the database a guide that says what each table is for, that the latest progress row for a book is where I am, to look a book up by title before adding it so there are no duplicates, and the queries for "how's my reading year going" (books, pages and average rating finished this year) and "which tags I read most and rate highest" (json_each over tags).

From then on: when I mention a book I want to read, add it with its author, pages and tags. When I start one, set it to reading with started_on. When I tell you what page I'm on, add a progress row. When I finish, set finished_on, my rating and my notes; when I give up on one, set it to abandoned. Show me the tables when you're finished.

Ask for the database

You don't write the schema. Describe what you want:

Set up a reading log in databasedmcp: books with title, author, page count, tags, status (want to read, reading, finished, abandoned), dates, my rating out of 5 and my notes. Also log my progress when I tell you what page I'm on.

Grok creates a database called reading and its tables:

schema
CREATE TABLE books (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL,
  author TEXT NOT NULL,
  pages INTEGER,
  tags TEXT NOT NULL DEFAULT '[]',
  status TEXT NOT NULL DEFAULT 'want' CHECK (status IN ('want', 'reading', 'finished', 'abandoned')),
  started_on TEXT,
  finished_on TEXT,
  rating INTEGER CHECK (rating BETWEEN 1 AND 5),
  notes TEXT,
  added_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE progress (
  id INTEGER PRIMARY KEY,
  book_id INTEGER NOT NULL REFERENCES books(id),
  on_day TEXT NOT NULL DEFAULT (date('now')),
  page INTEGER NOT NULL
);

It also writes the database a guide on how the tables are meant to be used. The guide comes back with the schema whenever an assistant looks the database up. Grok files things the same way next week as today, and so does any other assistant you connect.

guide
# reading: books and progress

- **books**: one row per book. status: want, reading, finished, abandoned. `tags` is a JSON array of lowercase strings, e.g. ["fiction", "sci-fi"]. `rating` is 1 to 5, set when I finish. `notes` is what I thought, in my words.
- **progress**: the page I'm on, one row each time I say. The latest row per book is where I am.

Look a book up by title (LIKE) before adding it.

This year: `SELECT count(*) AS books, sum(pages) AS pages, round(avg(rating), 1) AS avg_rating FROM books WHERE status = 'finished' AND finished_on >= date('now', 'start of year')`

By tag: `SELECT t.value AS tag, count(*) AS books, round(avg(b.rating), 1) AS avg_rating FROM books b, json_each(b.tags) t WHERE b.status = 'finished' GROUP BY t.value ORDER BY books DESC`

Use it

From here on you talk, and Grok writes the rows. Each request below is one statement:

Add two to my list: The Salt Orchard by Ilse Varga, 342 pages, literary fiction, and Quiet Engines by Tomas Aalto, 214 pages, a sci-fi novella.
execute
INSERT INTO books (title, author, pages, tags) VALUES (?, ?, ?, ?), (?, ?, ?, ?)
-- params: ["The Salt Orchard","Ilse Varga",342,"[\"fiction\", \"literary\"]","Quiet Engines","Tomas Aalto",214,"[\"fiction\", \"sci-fi\", \"novella\"]"]
Started The Salt Orchard tonight.
execute
UPDATE books SET status = 'reading', started_on = date('now') WHERE id = ? AND status = 'want'
-- params: [1]
I'm on page 112.
execute
INSERT INTO progress (book_id, page) VALUES (?, ?)
-- params: [1,112]
Finished it. Four stars: the middle dragged, but the last chapter made up for it.
execute
UPDATE books SET status = 'finished', finished_on = date('now'), rating = ?, notes = ? WHERE id = ?
-- params: [4,"The middle dragged, but the last chapter made up for it.",1]

Ask it questions

Once there's data, each report you'd pay for is a single query:

How's my reading year going?
query
SELECT count(*) AS books, sum(pages) AS pages, round(avg(rating), 1) AS avg_rating FROM books WHERE status = 'finished' AND finished_on >= date('now', 'start of year')
What kinds of books do I rate highest?
query
SELECT t.value AS tag, count(*) AS books, round(avg(b.rating), 1) AS avg_rating FROM books b, json_each(b.tags) t WHERE b.status = 'finished' GROUP BY t.value ORDER BY avg_rating DESC, books DESC

json_each turns each book's tag list into rows, so one book counts towards every tag it has.

Something short from my list, under 300 pages?
query
SELECT title, author, pages FROM books WHERE status = 'want' AND pages < ? ORDER BY pages
-- params: [300]

You can also open the database on the website, page through its rows and run read-only SQL yourself.

What you give up

There's no catalogue. Goodreads and StoryGraph know every book, its cover and its page count. Here, a book has the title, author and pages you or Grok wrote down. It has no cover, since databasedmcp keeps text and numbers, not images. You can't import the shelves you keep in another app either.

It's private, which is the point and also the cost. You won't see friends' updates, other readers' reviews or recommendations built from what millions of people read. People you share the account with can see the log, and Grok can suggest a next book from your notes, but it's your reading, not a community's.

Try it

databasedmcp is free to start, with no card. Free has 100 tool calls a week, enough to set this up and try it for a week. Starter has 1,000 for everyday use.

Create an account

More articles · databasedmcp · Docs