hatena-blog-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@hatena-blog-mcp draft a new blog post about MCP servers"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
hatena-blog-mcp
An MCP server for creating and updating Hatena Blog articles. It thinly wraps the Hatena Blog AtomPub API so that AI agents can draft, revise, and publish articles.
Setup
The package manager is pnpm (fixed via the packageManager field).
pnpm install # 依存のインストールと同時に prepare で dist がビルドされるObtaining configuration values
The "Root endpoint" and "API key" are displayed under Hatena Blog's [Settings] > [Advanced Settings] > [AtomPub]. The root endpoint has the following format.
https://blog.hatena.ne.jp/{ブログ所有者のはてなID}/{ブログID}/atomEnvironment variable | Required | Value |
| Yes | The Hatena ID of the account used for authentication (the owner of the API key) |
| Yes | The |
| Yes | API key |
| The |
For a blog you own, the owner and the operator are the same, so
HATENA_BLOG_OWNER_IDis not neededFor a shared blog (such as a company tech blog), the owner and the operator differ. In that case, specify the blog owner's ID in
HATENA_BLOG_OWNER_IDand your own account inHATENA_IDEven if you use a custom domain on a paid plan, specify the domain before the custom domain setting in
HATENA_BLOG_ID
See .env.example.
Registering with an MCP client
For Claude Code:
# 自分が所有するブログ
claude mcp add hatena-blog -s user \
-e HATENA_ID=your-hatena-id \
-e HATENA_BLOG_ID=your-blog.hatenablog.com \
-e HATENA_API_KEY=your-api-key \
-- node /absolute/path/to/hatena-blog-mcp/dist/index.js
# 共有ブログ(所有者と操作者が異なる場合は HATENA_BLOG_OWNER_ID を足す)
claude mcp add hatena-blog -s user \
-e HATENA_ID=your-hatena-id \
-e HATENA_BLOG_OWNER_ID=blog-owner-id \
-e HATENA_BLOG_ID=blog-owner-id.hatenablog.com \
-e HATENA_API_KEY=your-api-key \
-- node /absolute/path/to/hatena-blog-mcp/dist/index.jsAdding -s user makes it available across all projects. Do not use -s project (the API key will be written to .mcp.json).
When writing directly to the configuration file:
{
"mcpServers": {
"hatena-blog": {
"command": "node",
"args": ["/absolute/path/to/tech-blog/dist/index.js"],
"env": {
"HATENA_ID": "your-hatena-id",
"HATENA_BLOG_OWNER_ID": "blog-owner-id",
"HATENA_BLOG_ID": "blog-owner-id.hatenablog.com",
"HATENA_API_KEY": "your-api-key"
}
}
}
}Once registered, calling get_blog_info serves as a connectivity check.
Related MCP server: Blogger MCP Server
Tools
Blog-wide
Tool | Description |
| Retrieves the blog title and available collections (also usable as a connectivity check) |
| Lists the categories used in the blog |
Entries
Tool | Description |
| Lists entries in reverse chronological order (including drafts). Use |
| Traverses pages and performs partial-match search on title, body, and categories |
| Retrieves a single entry (the body remains in the registered notation) |
| Creates a new entry (draft by default) |
| Updates an entry with a diff-based update |
Pages
list_pages / search_pages / get_page / create_page / update_page are provided in the same form as entries.
Pages are only available on Hatena Blog paid plans (a 404 is returned on the free plan).
Pages do not have categories, so there is no categories parameter.
Design decisions
Deletion is not implemented
Deletion of entries and pages (DELETE) exists on the API side but is intentionally not exposed as a tool.
The impact of an accidental operation is too large and cannot be undone. Deletion should be done from the browser.
update_entry performs diff-based updates
Since AtomPub's PUT "replaces everything with the sent content," even when you only intend to fix the title,
you must resend the body, categories, and post date/time in full.
This server performs a GET followed by replacing only the specified items and then PUT inside update_entry.
Omitted items retain their current values
Omitting
updatedleaves the entry's post date/time (the displayed date) unchangedPassing
categoriesresults in a replacement (not an addition). To keep existing categories, include them as well
New entries are drafts by default
The draft parameter of create_entry defaults to true. To prevent an agent operation from immediately publishing an entry,
publishing only occurs when draft: false is explicitly specified.
Body notation
For content_type, you can specify text/x-markdown / text/x-hatena-syntax / text/html / text/plain (default is text/x-markdown).
However, how it is actually interpreted follows the blog's "edit mode" setting, so it must be written to match the blog's settings.
When updating an existing entry, the notation before editing is carried over.
Scheduled posting
Specify draft: true + scheduled: true + a future date/time for updated in create_entry.
List pagination
The Hatena Blog API returns few items per page, and the count is determined by the API side
(the official documentation states 7 entries, but we have confirmed that 10 are actually returned).
list_entries returns one page, and passing next_page as the page of the next call fetches more.
To search across multiple entries at once, use search_entries, which traverses pages internally. Control the traversal amount with max_pages.
Authentication and the Hatena ID in the URL
WSSE authentication (the X-WSSE header) is used. A Nonce and Created are generated for each request,
and Base64(SHA1(Nonce + Created + API key)) is sent as the PasswordDigest.
Note that the Hatena ID in the endpoint URL (the blog owner) and the account being authenticated are different things. Since API keys are issued per account rather than per blog, for a shared blog the combination is:
URL:
https://blog.hatena.ne.jp/{owner's ID}/{blog ID}/atomAuthentication: your account's Hatena ID + API key
Confusing the two results in a 401 (the key does not belong to the owner) or
a 403 (the account does not have permission for the blog).
This server separates the two with HATENA_BLOG_OWNER_ID and HATENA_ID,
and treats them as the same ID when omitted, so the same configuration method works for both your own blog and shared blogs.
Out of scope
Image upload: Outside the scope of AtomPub (the Hatena Fotolife API exists separately)
Changing page layouts: Not supported by the API. Configure from the browser
OAuth authentication: Only WSSE authentication with an API key is supported
Development
pnpm run typecheck # 型チェック
pnpm test # ユニットテスト(API はモック)
pnpm run build # dist へビルド
pnpm run dev # ビルドせずに起動
pnpm run inspect # MCP Inspector で手動確認Since pnpm 10 blocks dependency build scripts by default, only esbuild (used by tsx) is
allowed via pnpm.onlyBuiltDependencies in package.json.
Structure
src/
index.ts エントリポイント(stdio トランスポート)
server.ts McpServer の組み立て
config.ts 環境変数の読み込み
hatena/
client.ts AtomPub の HTTP クライアント
wsse.ts WSSE 認証ヘッダの生成
atom.ts Atom XML のパース・生成
types.ts ドメイン型
tools/
blog.ts ブログ全体に対するツール
collection.ts 記事・固定ページ共通のツール定義
shared.ts ツールの共通ヘルパーSince entries and pages have nearly the same structure on AtomPub, registerCollectionTools in tools/collection.ts
is called with two different configurations: one for entries and one for pages.
License
MIT License. See LICENSE for details.
Available Tools
13 toolscreate_entryブログ記事作成A
ブログ記事を新規作成する。既定では下書きとして作成されるので、公開する場合は draft を false にする。予約投稿する場合は draft=true・scheduled=true と、未来日時の updated を指定する。
Inputs: title (required), content (required), draft, updated, +5 more.
create_page固定ページ作成A
固定ページを新規作成する。既定では下書きとして作成されるので、公開する場合は draft を false にする。予約投稿する場合は draft=true・scheduled=true と、未来日時の updated を指定する。 固定ページははてなブログの有料プランでのみ利用できる。無料プランでは 404 が返る。
Inputs: title (required), content (required), draft, updated, +4 more.
get_blog_infoブログ情報取得ARead-only
接続先ブログのタイトルと、利用できるコレクション(記事・固定ページ)を取得する。設定と認証が正しいかの疎通確認にも使える。固定ページのコレクションは有料プランでのみ返る。
Inputs: no named parameters.
get_entryブログ記事取得ARead-only
ブログ記事を 1 件取得する。本文(登録記法のまま)・カテゴリ・公開状態を含む。編集前に必ずこれで現状を確認する。
Inputs: entry_id (required), include_formatted_content.
get_page固定ページ取得ARead-only
固定ページを 1 件取得する。本文(登録記法のまま)・カテゴリ・公開状態を含む。編集前に必ずこれで現状を確認する。 固定ページははてなブログの有料プランでのみ利用できる。無料プランでは 404 が返る。
Inputs: page_id (required), include_formatted_content.
list_categoriesカテゴリ一覧ARead-only
ブログで使われているカテゴリの一覧を取得する。記事を作成・更新する前に、既存のカテゴリ名と表記を揃えるために確認する。
Inputs: no named parameters.
list_entriesブログ記事一覧ARead-only
ブログ記事を新しい順に一覧する。下書きも含まれる。1 ページあたりの件数は API 側で決まっており、続きを読むには戻り値の next_page を page に渡す。本文まで読みたい場合は get_entry を使う。
Inputs: page, include_content.
list_pages固定ページ一覧ARead-only
固定ページを新しい順に一覧する。下書きも含まれる。1 ページあたりの件数は API 側で決まっており、続きを読むには戻り値の next_page を page に渡す。本文まで読みたい場合は get_page を使う。 固定ページははてなブログの有料プランでのみ利用できる。無料プランでは 404 が返る。
Inputs: page, include_content.
search_entriesブログ記事検索ARead-only
ブログ記事をページを辿りながら検索する。タイトル・本文・カテゴリを対象に部分一致(大文字小文字は無視)。はてなブログの API は一覧の 1 ページあたり件数が少ないため、まとめて探すときはこのツールを使う。古いブログ記事まで届かない場合は max_pages を増やす。
Inputs: limit, query, status, category, +2 more.
search_pages固定ページ検索ARead-only
固定ページをページを辿りながら検索する。タイトル・本文・カテゴリを対象に部分一致(大文字小文字は無視)。はてなブログの API は一覧の 1 ページあたり件数が少ないため、まとめて探すときはこのツールを使う。古い固定ページまで届かない場合は max_pages を増やす。 固定ページははてなブログの有料プランでのみ利用できる。無料プランでは 404 が返る。
Inputs: limit, query, status, max_pages, +1 more.
update_entryブログ記事更新A
ブログ記事を更新する。指定した項目だけを差し替える差分更新で、省略した項目は現在の値がそのまま残る。下書きを公開するには draft=false を指定する。categories を渡すと現在のカテゴリは完全に置き換わる。
Inputs: entry_id (required), draft, title, content, +5 more.
update_page固定ページ更新A
固定ページを更新する。指定した項目だけを差し替える差分更新で、省略した項目は現在の値がそのまま残る。下書きを公開するには draft=false を指定する。categories を渡すと現在のカテゴリは完全に置き換わる。 固定ページははてなブログの有料プランでのみ利用できる。無料プランでは 404 が返る。
Inputs: page_id (required), draft, title, content, +4 more.
upload_image画像アップロードA
ローカルの画像をはてなフォトライフにアップロードし、記事本文に貼れる記法(embed)を返す。embed は Markdown・はてな記法の編集モード向け。見たままモードのブログでは imageUrl を使う。画像は認証アカウント(HATENA_ID)のフォトライフに保存され、URL を知っていれば誰でも見られる。社外に出してよい画像だけを渡すこと。アップロードした画像の削除はブラウザから行う。
Inputs: file_path (required), title, folder.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 13 tools
Each tool maps to a distinct resource and action: entries, pages, categories, blog info, and image upload are cleanly separated. The list/search/get/create/update split is explicit, and descriptions clarify when to use list versus search.
All tool names use consistent snake_case verb_noun patterns such as list_entries, get_entry, create_page, and update_page. Even the auxiliary tools get_blog_info, list_categories, and upload_image fit the same readable convention.
With 13 tools, the set is well-scoped: entry CRUD/list/search, page CRUD/list/search, plus blog info, categories, and image upload. Each tool has a clear place, and the symmetric entries/pages coverage is reasonable rather than redundant.
The surface covers create, read, update, list, and search for both entries and pages, but deletion operations for entries and pages are missing. Image upload exists without an accompanying delete tool, with deletion explicitly delegated to the browser, leaving lifecycle gaps.
Maintenance
Related MCP Connectors
Travel tools for AI agents: plan and edit real trips, search stays and tours, import travel videos.
Create, edit, organize, publish, and configure JustBlogged blogs from MCP clients.
SEO & marketing toolkit for AI agents: GA4, Search Console, AdSense, GTM, PageSpeed, Trends.
Manage a WordPress site from your AI assistant: read, search, propose edits, Search Console data.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables searching and retrieving articles from Hatena Blog through Claude Desktop/Web. Supports keyword search, fetching recent posts, and retrieving post details by URL.1MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with the Google Blogger API v3 to manage blog posts and metadata. It supports the full post lifecycle including creating, updating, publishing, and deleting content through natural language.105 npm1MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI models to interact with Google Blogger blogs, manage posts, labels, and retrieve blog information via API key or OAuth2.8 npmMIT
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to publish, update, and manage Hashnode blog articles, with support for tags, cover images, and publication management.-