Hardcover OAuth MCP

io.github.benjuntilla由 GitHub 帳號 benjuntilla 發布v0.1.0更新於 Nov 4, 2026

Read and update your Hardcover library, progress, lists, and goals. Sign in with Hardcover OAuth.

已驗證Streamable HTTP可網頁執行效率與工作流知識與記憶

概覽

AI 產生的概覽

遠端 MCP 伺服器,透過 OAuth 登入讓助理讀取與更新你在 Hardcover 的書櫃、閱讀進度、書評、日誌、書單與閱讀目標。

可以做什麼
  • 搜尋目錄並查詢書籍、版本、作者、系列與熱門書籍
  • 讀取你的書櫃、正在閱讀清單、書評、閱讀紀錄與個人資料
  • 修改閱讀狀態、頁數進度、評分、書評、擁有的版本與書櫃項目
  • 管理日誌條目、排序書單、閱讀目標、追蹤與通知
  • 執行原始 GraphQL 查詢、變更與刪除,並提供操作與型別查詢工具
適用情境
適合在 Hardcover 記錄閱讀的人:想透過網頁、手機或桌面助理以對話方式記錄進度、標記讀完、寫書評、整理書單或設定目標,而不必手動操作網站。
執行需求
需要 Hardcover 帳號,以及支援遠端 Streamable HTTP 與 OAuth 的用戶端,無需貼上 API 金鑰。可直接連線託管端點;自行架設則需 mise、Cloudflare 帳號與註冊的 Hardcover 開發者應用程式(HARDCOVER_CLIENT_ID、HARDCOVER_CLIENT_SECRET)。
安裝前請注意
它會寫入你的帳號:工具可新增、修改與刪除書櫃項目、書評、日誌、書單、目標、追蹤與閱讀紀錄,原始變更與刪除工具還能觸及 API 其餘部分。只授予需要的權限,並可在 Hardcover 的已授權應用程式頁面撤銷。部分工具需要付費 Supporter 會員或 Librarian 角色。請求共用 Hardcover 的每使用者速率限制。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Hardcover OAuth MCP,將其新增到工作區。
  2. 連接 所需的 憑證。它們會被私密儲存,絕不會在公開頁面上展示。
  3. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.benjuntilla%2Fhardcover-oauth-mcp/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。 客戶端會在首次連接時完成 OAuth 登入。

{
  "mcpServers": {
    "hardcover-oauth": {
      "type": "http",
      "url": "https://hardcover.benjuntilla.com/mcp"
    }
  }
}

README

hardcover-oauth-mcp

Manage your Hardcover library, reading progress, reviews, lists, and goals from Claude, ChatGPT, and other AI assistants with this remote Model Context Protocol (MCP) server. Connect to the public instance at https://hardcover.benjuntilla.com/mcp (quick start) or deploy your own.

  • Works in web and mobile clients. The public instance is a hosted remote server, so Claude on the web and on phones, ChatGPT, and other remote clients can connect to it. Other Hardcover MCP servers run on your own computer, where only desktop clients can reach them.
  • Sign in with Hardcover (OAuth). No pasting unsafe API keys. Each person connects their own account through Hardcover's OAuth and picks which permissions to grant.
  • 53 read/write tools. 47 custom task-oriented tools cover the library, progress, reviews, journal, lists, goals, follows, notifications, and vibes. Six raw GraphQL and schema-discovery tools reach anything else in the Hardcover API.

Example workflows

Track a book

  1. "I'm on page 212 of Piranesi." The book moves to Currently Reading and the page goes on its reading session.
  2. "Finished it today, 4.5 stars." The book moves to Read, finished today, with a 4.5-star rating.

[Claude, asked "I'm on page 212 of Piranesi by Susanna Clarke," checks Currently Reading, searches Hardcover, and updates the reading progress]

Plan what's next

  1. "Add Kindred and The Dispossessed to my want-to-read."
  2. "Make a ranked list called Summer with both, Kindred first."
  3. "Move The Dispossessed to the top."

Set a reading goal

  1. "Set a goal of 30 books this year."
  2. "How am I doing on my goal?"

Keep a journal

  1. "Save this quote from Piranesi: 'The Beauty of the House is immeasurable; its Kindness infinite.'"
  2. "Show my notes on Piranesi."

Pick an edition

  1. "Which audiobook editions of Dune are there, and how long are they?"
  2. "Switch my copy to the shortest one."

Ask anything else

  1. "Which of the books I read last year had the most pages?" With no tool for that, the client looks up the API with hardcover_find_operations and runs a read-only hardcover_query.
  2. "Answer the prompt 'What book made you cry uncontrollably?' with Kindred." The client finds the prompt with hardcover_search, looks up the mutation with hardcover_find_operations, and runs hardcover_mutate.

Quick start

Anyone with a Hardcover account can use the public instance. Add this URL to your MCP client as a remote server:

text
https://hardcover.benjuntilla.com/mcp
  • Claude (web, desktop, mobile): Settings → Connectors → Add custom connector, then paste the URL.
  • Claude Code: claude mcp add --transport http hardcover https://hardcover.benjuntilla.com/mcp, then run /mcp to sign in.
  • ChatGPT (web, desktop, mobile): on chatgpt.com, open Plugins, select + → Add custom MCP server, paste the URL, keep OAuth as the authentication, and create it. Type @ in a chat to use it.
  • Cursor and others: add a remote (Streamable HTTP) server with that URL. The client discovers OAuth by itself.
  • MCP Inspector: bunx @modelcontextprotocol/inspector, choose Streamable HTTP, and enter the URL.

Your client opens a consent page where you pick permissions, then Hardcover asks you to sign in.

[The consent page, where you choose which Hardcover permissions the client gets]

Revoke access any time from Hardcover's Authorized apps page. See the privacy notice and terms, or deploy your own.

[Hardcover's Authorized apps page, listing Hardcover OAuth MCP with its scopes and sessions and a button to revoke access]

Report an issue

Something not working? Open an issue on GitHub, or email [email protected]. For security problems, follow the security policy instead.

How it works

It runs on the Cloudflare Developer Platform (Workers, Durable Objects, and KV), chosen for its convenient developer experience and cost efficiency. A Durable Object per connection holds the tokens and serves MCP; KV holds OAuth state. Alchemy deploys it in one command, and alchemy dev runs the same code locally. It's built with Effect 4 (including Effect's own MCP server), TypeScript 7, Bun, mise, and Astro.

diagram
┌──────────────┐  MCP + OAuth 2.1   ┌──────────────────────────────┐│ MCP client   │ ─────────────────▶ │ Worker                       ││ (Claude, …)  │ ◀───────────────── │  OAuthProvider, consent page │└──────────────┘  MCP access token  │  auth + rate limits on /mcp  │                                    └──────────────┬───────────────┘                                                   │ one per connection                                    ┌──────────────▼───────────────┐                                    │ HardcoverConnection (DO)     │                                    │  Hardcover tokens            │                                    │  Effect McpServer + tools    │                                    └──────────────┬───────────────┘                                                   │ OAuth + GraphQL                                    ┌──────────────▼───────────────┐                                    │ Hardcover API                │                                    └──────────────────────────────┘

The Worker is an OAuth authorization server for MCP clients, built on @cloudflare/workers-oauth-provider. It supports dynamic client registration and Client ID Metadata Documents.

The Worker checks each /mcp request (token, allowlist, the server's own rate limit, scopes) and forwards it to the connection's Durable Object. The object runs Effect's MCP server. It speaks the sessionless 2026-07-28 revision as well as 2025-11-25, 2025-06-18, and 2025-03-26. Sessions for the 2025 revisions live in the object's memory. When Cloudflare evicts an idle object, its sessions end: the client gets a 404 and, as the protocol requires, starts a new session.

Tools

Kinds: read, write (adds or changes data), and delete. A tool appears only if you chose its scopes for your connection.

All 53 tools
ToolWhat it doesKindScopesNeeds
hardcover_meGet your Hardcover profilereadread:me:content
hardcover_get_userLook up a readerreadread:users
hardcover_list_followsList followsreadread:social
hardcover_follow_userFollow a readerwritewrite:social, read:users
hardcover_unfollow_userUnfollow a readerdeletewrite:social, read:users
hardcover_list_notificationsList notificationsreadread:notifications
hardcover_mark_notifications_readMark notifications readwritewrite:notifications
hardcover_searchSearch Hardcoverreadread:catalog
hardcover_get_bookGet a bookreadread:catalog
hardcover_get_editionsGet editionsreadread:catalog
hardcover_get_authorGet an authorreadread:catalog
hardcover_get_seriesGet a seriesreadread:catalog
hardcover_trending_booksTrending booksreadread:catalog
hardcover_list_vibesList your vibesreadread:vibes
hardcover_create_vibeCreate a vibewritewrite:vibesSupporter
hardcover_list_libraryList your libraryreadread:library
hardcover_currently_readingCurrently readingreadread:library
hardcover_list_reviewsList your reviewsreadread:library
hardcover_get_library_entryGet your entry for a bookreadread:library
hardcover_set_statusSet reading statuswritewrite:library, read:library
hardcover_update_progressUpdate reading progresswritewrite:library, read:library
hardcover_mark_finishedMark a book finishedwritewrite:library, read:library
hardcover_rate_bookRate a bookwritewrite:library, read:library
hardcover_write_reviewWrite a reviewwritewrite:library, write:reviews, read:library
hardcover_delete_reviewDelete a reviewdeletewrite:library, write:reviews, read:library
hardcover_update_library_entryEdit your entry for a bookwritewrite:library, read:library
hardcover_set_ownedMark an edition ownedwritewrite:library, read:lists, write:lists
hardcover_remove_from_libraryRemove a book from your librarydeletewrite:library, read:library
hardcover_add_readAdd a reading sessionwritewrite:library, read:library
hardcover_update_readEdit a reading sessionwritewrite:library, read:library
hardcover_delete_readDelete a reading sessiondeletewrite:library, read:library
hardcover_list_journalList journal entriesreadread:journal
hardcover_add_journal_entryAdd a journal entrywritewrite:library
hardcover_update_journal_entryEdit a journal entrywritewrite:library
hardcover_delete_journal_entryDelete a journal entrydeletewrite:library
hardcover_list_listsList your listsreadread:lists
hardcover_get_listGet a listreadread:lists, read:catalog
hardcover_create_listCreate a listwritewrite:lists
hardcover_update_listEdit a listwritewrite:lists, read:lists
hardcover_delete_listDelete a listdeletewrite:lists, read:lists
hardcover_add_to_listAdd a book to a listwritewrite:lists
hardcover_remove_from_listRemove a book from a listdeletewrite:lists, read:lists
hardcover_reorder_listReorder a listwritewrite:lists, read:lists
hardcover_list_goalsList your reading goalsreadread:goals
hardcover_create_goalCreate a reading goalwritewrite:goals
hardcover_update_goalEdit a reading goalwritewrite:goals, read:goals
hardcover_delete_goalDelete a reading goaldeletewrite:goals, read:goals
hardcover_find_operationsFind Hardcover API operationsreadnone
hardcover_describe_typeDescribe a Hardcover GraphQL typereadnone
hardcover_queryRun a Hardcover GraphQL queryreadnone
hardcover_mutateRun a Hardcover GraphQL mutationwriteany write:* scopeSupporter for write:vibes
hardcover_deleteRun a Hardcover GraphQL deletiondeleteany write:* scopeSupporter for write:vibes
hardcover_catalog_editAdd to or edit the Hardcover catalogwriteany write:* catalog scopeLibrarian for write:catalog:edit, Librarian (book_mapper) for write:catalog:map

Supporter is a paid Hardcover membership and Librarian a Hardcover librarian role. Hardcover enforces both; a tool that always needs one says so in its title and description. Sign-in drops write:catalog:edit and write:catalog:map from accounts without the role, but anyone can add catalog records with write:catalog:append.

The raw tools check each document's operation kind, root fields, needed scopes, and size (at most 10 top-level fields) before sending it. They also reject text operators Hardcover has disabled, such as _like and _regex. Mistakes come back as clear errors instead of using up your Hardcover rate limit. hardcover_find_operations and hardcover_describe_type search an index built from Hardcover's API docs. hardcover_find_operations ranks operations by how well their names and return types match, so a phrase like "add a book to a list" works. For a type name that doesn't exist, hardcover_describe_type suggests the closest ones, so UserBook points to user_books.

Hardcover's rate limits are per user, and every app shares them. Each user gets 60 requests a minute (bursts of 10, or 15 for Supporters) and 5,000 a day (50,000 for Supporters). Each top-level field costs one request.

Deploy your own

You need mise, a Cloudflare account, and a Hardcover account. A custom domain is optional; without one, the server lives at https://hardcover-oauth-mcp.<your-subdomain>.workers.dev.

1. Install

sh
git clone https://github.com/benjuntilla/hardcover-oauth-mcpcd hardcover-oauth-mcpmise installcp .env.example .env

2. Register a Hardcover app

Create one at hardcover.app/account/developer-apps/new:

  • Application type: Web app (server-side). You can't change this later.
  • Redirect URIs: https://<your-domain>/callback, plus http://localhost:1337/callback for local runs.
  • Scopes this app may request: read:me:content read:me:roles read:catalog read:library write:library write:reviews read:journal read:lists write:lists read:goals write:goals read:users read:social write:social read:notifications write:notifications read:prompts write:prompts read:vibes write:vibes read:account write:catalog:append write:catalog:edit write:catalog:map openid offline_access. Leave all unticked, since it would also cover scopes Hardcover adds later.
  • Device Authorization Grant: off.

Put the client id and secret into .env as HARDCOVER_CLIENT_ID and HARDCOVER_CLIENT_SECRET. Hardcover shows the secret only once.

3. Configure

In alchemy.run.ts, edit DEPLOYMENTS. Each key is a stage: mise run deploy --stage prod uses prod, and mise run dev uses local.

ts
const DEPLOYMENTS: Readonly<Record<string, DeploymentSettings>> = {  local: { allowedUsers: ["*"] },  prod: { allowedUsers: ["your-username"], domain: "hardcover.example.com" },}
  • allowedUsers: your Hardcover username (or several, or numeric ids). Use "*" to let anyone connect, as the public instance does. Every person uses their own account and Hardcover rate limit.
  • domain: a hostname on a zone in your Cloudflare account. Leave it out to use the auto-assigned workers.dev URL.

4. Sign Alchemy in to Cloudflare

sh
bun alchemy profile edit --add Cloudflare

5. Deploy

sh
mise run deploy --stage prod

This builds the site, creates the Cloudflare resources, and prints the URL. Run it again after changes. mise run logs --stage prod tails logs. mise run destroy --stage prod removes everything.

Deploys keep Alchemy's state in your Cloudflare account, so any machine signed in with Alchemy can redeploy or destroy. The first deploy sets up the state store there. mise run dev and the tests keep theirs in .alchemy/.

Pushes to main deploy prod once mise run check and mise run test:e2e pass. This needs a main-only production environment with a CLOUDFLARE_ACCOUNT_ID variable and CLOUDFLARE_API_TOKEN, HARDCOVER_CLIENT_ID, and HARDCOVER_CLIENT_SECRET secrets. The token needs Account Settings and Zone read, plus Workers Scripts, Workers KV Storage, Secrets Store, Workers Routes, and SSL and Certificates edit.

  • Plan: use Workers Paid. A connection's Durable Object builds its MCP server when it wakes. That takes about 100 ms of CPU, ten times the Free plan's per-request limit. After that, a call takes about 5 ms.
  • The server's own rate limits: 10 registrations, 30 sign-in steps, and 60 token requests a minute per client IP. Each Hardcover account gets 120 MCP requests a minute.
  • Observability: Workers Logs, Traces, and Issues are on. Cloudflare's request logs record each request's path, status, headers, and client IP, but not its query string or body. Cloudflare redacts the authorization and cookie headers. Leaving out query strings keeps Hardcover's one-time sign-in code out of logs and traces. What the token grants reaches the Durable Object as a method argument rather than a header, so it stays out of the logs. The OAuth provider files grants under a keyed pseudonym of the Hardcover user id, so the storage keys in traces don't reveal it. The Worker logs unexpected failures (defects) without tokens or request data, and Issues groups them. Expected ones, such as Hardcover rate limits, revoked access, or bad queries, go back to the agent as tool errors.

6. Connect a client

Connect the same way as the public instance, with https://<your-domain>/mcp as the URL.

Run locally

With the app and .env from steps 1 and 2 above, the whole flow works on your machine:

  1. Run mise run dev. It serves the Worker in workerd at http://localhost:1337, with local KV and Durable Objects, and reloads on code changes. It builds the static pages (README.md, PRIVACY.md, TERMS.md, SECURITY.md, and site/) once at start, so restart it to see changes to them. You don't need a Cloudflare account.
  2. Connect a client on the same machine to http://localhost:1337/mcp, for example claude mcp add --transport http hardcover-local http://localhost:1337/mcp.

來源:README.md,提交 553052d

工具

0
該伺服器需要登入,因此 SourceWeft 無法在沒有帳號的情況下讀取其工具,也未收錄。已連接帳號所能看到的內容可能因帳號及其權限而異。

版本歷史

1
  1. v0.1.0最新Oct 21, 2026

評分

已滿足適用檢查項的 85%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分