Hatena博客MCP服务器

ChatGPT通过可以操作博客MCP(Model Context Protocol)服务器。Cloudflare Workers + Durable Objects而需要与环境混合的每条反射光线,进行环境采样。
主要特征
- ChatGPT直接操作博客:可以浏览、创建和更新文章
- 安全的两层OAuth验证:
- ChatGPT ↔ MCP服务器:OAuth 2.1 + PKCE + JWT (RS256) - MCP服务器↔ 博客大巴OAuth 1.0a
- 完全无服务器: Cloudflare Workers + Durable Objects最低运营成本
- 模块化设计:根Durable Object、可维护的业务逻辑实施
示威
User: 最新のブログ記事を3件表示して
ChatGPT: (list_entriesツールを使用)
1. タイトル1 - 2025-11-27
2. タイトル2 - 2025-11-26
3. タイトル3 - 2025-11-25
User: 新しい記事を下書きで作成して
タイトル: CloudflareでMCPサーバーを作った話
本文: ...
ChatGPT: (create_entryツールを使用)
下書きを作成しました!快速启动
前提条件
- 包子 v1.0以上
- Cloudflare账户
- 账号
1.安装
git clone https://github.com/your-username/hatena-blog-mcp.git
cd hatena-blog-mcp
bun install2.哈哈OAuth注册应用程序
- 空手OAuth应用程序注册页面访问
- 创建新应用程序
- 回调URL:
https://your-worker-name.workers.dev/hatena/oauth/callback - 消费者密钥和消费者秘密获取并记录
3. OAuth生成凭据
使用以下命令JWT密钥对和OAuth生成客户端信息:
bun run setup复制输出的环境变量。
4.设置环境变量
.dev.vars创建文件并设置:
# はてなブログのOAuth 1.0a認証情報
HATENA_CONSUMER_KEY=your_hatena_consumer_key_here
HATENA_CONSUMER_SECRET=your_hatena_consumer_secret_here
# MCPサーバーのOAuth 2.1設定
OAUTH_ISSUER=https://your-worker-name.workers.dev
OAUTH_CLIENT_ID=generated_client_id_from_setup
OAUTH_CLIENT_SECRET=generated_client_secret_from_setup
OAUTH_REDIRECT_URIS=https://chatgpt.com/oauth-callback-url,https://claude.ai/api/mcp/auth_callback,https://claude.com/api/mcp/auth_callback
SETUP_SECRET=a_strong_random_string_for_setup_auth
# JWT署名鍵(bun run setupで生成)
JWT_PUBLIC_KEY={"kid":"...","alg":"RS256",...}
JWT_PRIVATE_KEY={"kid":"...","alg":"RS256",...}5.部署
# Cloudflare Workersにデプロイ
bun run deploy
# デプロイ後、OAuthクライアントを登録(初回のみ)
curl -X POST https://your-worker-name.workers.dev/oauth/setup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SETUP_SECRET" \
-d '{
"client_id": "OAUTH_CLIENT_IDの値",
"client_secret": "OAUTH_CLIENT_SECRETの値",
"redirect_uris": [
"https://chatgpt.com/oauth-callback-url",
"https://claude.ai/api/mcp/auth_callback",
"https://claude.com/api/mcp/auth_callback"
]
}'6. ChatGPT连接
- ChatGPT的,之MCP打开设置
- 设置:
- 统一资源定位符: https://your-worker-name.workers.dev/mcp - 验证类型:OAuth - 客户端ID: OAUTH_CLIENT_ID的值 - 客户端密钥: OAUTH_CLIENT_SECRET的值
- 接続后、
start_hatena_oauth工具与博客合作
Claude 使用时OAuth 回调URL 作为 https://claude.ai/api/mcp/auth_callback(将来 https://claude.com/api/mcp/auth_callback ),模板名称将采用不同的格式 redirect_uris 中描述的相应参数的值。
可用的MCP工具
start_hatena_oauth
和博客的OAuth开始协作。已返回URL中所述修改相应参数的值。
// 入力: なし
// 出力:
{
"authorizeUrl": "https://www.hatena.com/oauth/authorize?...",
"state": "uuid-string"
}list_entries
获取博客文章列表。
// 入力:
{
"blogId": "username.hatenablog.com", // 必須
"limit": 10, // オプション
"offset": 0 // オプション
}create_entry
创建新的博客文章。
// 入力:
{
"blogId": "username.hatenablog.com", // 必須
"title": "記事のタイトル", // 必須
"content": "# 本文\nMarkdown形式", // 必須
"draft": true // オプション(デフォルト: false)
}update_entry
更新现有文章。
// 入力:
{
"blogId": "username.hatenablog.com", // 必須
"entryId": "12345678901234567890", // 必須
"title": "新しいタイトル", // オプション
"content": "新しい本文", // オプション
"draft": false // オプション
}save_blog
博客大巴ID中所述修改相应参数的值。
// 入力:
{
"blogId": "username.hatenablog.com", // 必須
"title": "マイブログ", // オプション
"url": "https://username.hatenablog.com" // オプション
}list_saved_blogs
获取已保存的博客列表。
// 入力: なし体系结构
系统配置
┌─────────────────────────────────────────────────────────────┐
│ ChatGPT │
└─────────────────────────────────────────────────────────────┘
│
│ OAuth 2.1 + PKCE
│ Bearer JWT (RS256)
▼
┌─────────────────────────────────────────────────────────────┐
│ MCP Server (Cloudflare Workers) │
│ │
│ ┌─────────────┐ ┌──────────────────────────────────┐ │
│ │ Routes │ │ Durable Objects │ │
│ │ │ │ │ │
│ │ ・discovery │ │ ・UserDurableObject │ │
│ │ ・oauth │ │ (ユーザー状態とトークン) │ │
│ │ ・mcp │ │ ・ClientDurableObject │ │
│ │ ・callback │ │ (OAuthクライアント情報) │ │
│ └─────────────┘ │ ・AuthCodeDurableObject │ │
│ │ (認可コード、TTL: 10分) │ │
│ ┌─────────────┐ │ ・OAuthStateDurableObject │ │
│ │ Libraries │ │ (はてなOAuth一時状態) │ │
│ │ │ └──────────────────────────────────┘ │
│ │ ・jwt │ │
│ │ ・hatena │ │
│ │ ・state │ │
│ │ ・crypto │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ OAuth 1.0a
▼
┌─────────────────────────────────────────────────────────────┐
│ Hatena Blog AtomPub API │
└─────────────────────────────────────────────────────────────┘OAuth验证流程
ChatGPT → MCP服务器(OAUTh2.1 with PKCE)
- ChatGPT的
/.well-known/oauth-protected-resource的OAuth获取设置 - ChatGPT的
code_verifier,然后单击code_challenge = SHA256(code_verifier)计算 /oauth/authorize将用户重定向至(code_challenge),模板名称将采用不同的格式- MCP服务器生成授权代码
AuthCodeDurableObject保存到 - ChatGPT返回授权码
- ChatGPT的
/oauth/token授权码和code_verifier发送 - MCP服务器PKCE验证(
SHA256(code_verifier) == code_challenge) - 検证成功后、JWT(RS256署名)を発行
- ChatGPT以后
Authorization: Bearer的/mcp访问
MCP服务器-博客
- ChatGPT的
start_hatena_oauth运行工具 - MCP服务器是什么request token请求
- request token私钥
OAuthStateDurableObject暂存 authorizeUrl的ChatGPT归还- 用户免费授权
- 边长
/hatena/oauth/callback重新定位 - MCP服务器access token获得
- access token的
UserDurableObject永久保存 - 以后,到尽头API请求access token使用
目录结构
src/
├── index.ts # エントリーポイント
├── types.ts # TypeScript型定義
│
├── routes/ # HTTPルート(Honoアプリ)
│ ├── discovery.ts # /.well-known/* エンドポイント
│ ├── oauth.ts # /oauth/* エンドポイント
│ ├── hatena-callback.ts # /hatena/oauth/callback
│ └── mcp.ts # /mcp エンドポイント
│
├── do/ # Durable Object定義
│ ├── user-do.ts # ユーザー状態管理
│ ├── client-do.ts # OAuthクライアント管理
│ ├── auth-code-do.ts # OAuth認可コード管理
│ ├── oauth-state-do.ts # はてなOAuth状態管理
│ └── access-token-do.ts # 将来の拡張用
│
├── lib/ # ビジネスロジック
│ ├── jwt.ts # JWT署名・検証(RS256)
│ ├── hatena.ts # はてなAPI呼び出し
│ ├── state.ts # Durable Object操作ヘルパー
│ └── crypto.ts # PKCE用SHA-256実装
│
└── mcp/ # MCP Server実装
└── server.ts # MCPツール定義とハンドラ
scripts/
└── setup.ts # JWT鍵ペアとOAuth情報生成
wrangler.toml # Cloudflare Workers設定
package.json # 依存関係本地开发
启动开发服务器
bun run dev开发服务器http://localhost:8787中所述修改相应参数的值。
本地测试
# Well-knownエンドポイントの確認
curl http://localhost:8787/.well-known/oauth-protected-resource
# JWKSの確認
curl http://localhost:8787/oauth/jwks调试
Cloudflare Workers查看日志:
wrangler tail故障排除
invalid_client 出现错误
/oauth/setup请检查客户端是否已在端点注册。
curl -X POST https://your-worker.workers.dev/oauth/setup \
-H "Content-Type: application/json" \
-d '{"client_id":"...","client_secret":"...","redirect_uris":["..."]}'Hatena account not linked 错误
start_hatena_oauth请先用工具完成与博客的合作。
PKCE验证错误
ChatGPT客户端正确code_verifier中描述的相应参数的值。
JWT验证错误
JWT_PUBLIC_KEY和JWT_PRIVATE_KEY确认是否正确设置- 两个密钥的
kid(Key ID)确认是否一致
环境变量引用
| 变数名 | 说明 | 例 |
|---|---|---|
HATENA_CONSUMER_KEY 哈哈OAuth应用程序Consumer Key | abcd1234... | |
HATENA_CONSUMER_SECRET 哈哈OAuth应用程序Consumer Secret | xyz789... | |
OAUTH_ISSUER | OAuth令牌发行者URL | https://your-worker.workers.dev |
OAUTH_CLIENT_ID | MCP客户机ID | UUID格式 |
OAUTH_CLIENT_SECRET | MCP客户端密码|随机字符串| | |
OAUTH_REDIRECT_URIS 重定向URI(逗号分隔) https://chatgpt.com/... , https://claude.ai/api/mcp/auth_callback | ||
JWT_PUBLIC_KEY | JWT検证用公开键(JWK形式) | JSON文字列 |
JWT_PRIVATE_KEY | JWT署名用秘密鍵(JWK形式) | JSON文字列 |
SETUP_SECRET | /oauth/setup 的管理员密钥(Bearer令牌) |
API 端点列表
发现端点
|端点|方法|说明| |---------------|---------|------| | /.well-known/oauth-protected-resource | GET | MCP OAuth资源元数据 | /.well-known/oauth-authorization-server | GET | OAuth授权服务器元数据
OAuth端点
|端点|方法|说明| |---------------|---------|------| | /oauth/authorize | GET | OAuth授权端点(支持PKCE)| | /oauth/token | POST | 获取令牌(授权代码→JWT) | | /oauth/jwks | GET | 公钥集(JWK Set) | /oauth/setup | POST | 客户端注册(仅第一次)
MCP端点
|端点|方法|说明| |---------------|---------|------| | /mcp | POST | MCP JSON-RPC端点(必须进行Bearer认证)
回调端点
|端点|方法|说明| |---------------|---------|------| | /hatena/oauth/callback | GET | 疑问OAuth回调
分发
欢迎拉式点播!在大的变更的情况下,首先issue中所述修改相应参数的值。
- 分叉此存储库
- 创建特征分支(
git checkout -b feature/amazing-feature) - 提交更改(
git commit -m 'Add amazing feature') - 推到分支(
git push origin feature/amazing-feature) - 创建拉式请求
许可证
MIT License - 了解更多信息许可证请参见文件。
