Phase 4 では、収集・要約した記事を Notion に保存し、蓄積データから パーソナライズ推薦 を行えるように拡張しました。
対象リポジトリ:https://github.com/RuumaLilja/tech-collector-mcp
✍ 本稿は ChatGPT でドラフト生成後、筆者が検証・加筆しています
1. これまでのおさらい
| フェーズ | 機能 | 記事 |
|---|---|---|
| Phase 0 | 構想・技術選定 | #0 |
| Phase 1 | Qiita 取得 & MCP 基盤 | #1 |
| Phase 2 | Gemini API 要約 | #2 |
| Phase 3 | マルチソース ingest | #3 |
| Phase 4 | Notion 連携 + 推薦 | ← 本記事 |
2. Notion 連携の概要
-
StoragePort … 抽象ストレージ層。Notion 以外(例:SQLite/Firestore)にも差し替え可能
-
syncService … 単一記事を upsert
-
syncBatchService … 並列同期+進捗表示
3. 簡易パーソナライズ推薦
3-1. コアロジック(要約版)
// src/services/recommenderService.js — essence
import { DECAY_RATE } from '../config/constants.js';
import { fetchAllArticles } from './fetchService.js';
// 1) 発行日が古いほど指数減衰
const decay = d =>
Math.exp(-DECAY_RATE * ((Date.now() - new Date(d)) / 86400000));
// 2) 読了記事のタグ×評価を重み化
async function tagWeights(storage) {
const read = await storage.listByStatus('読了', 100);
return read.reduce((w, a) => {
if (!a.rating) return w;
a.tags.forEach(t => (w[t] = (w[t] || 0) + a.rating));
return w;
}, {});
}
// 3) 未読記事に「タグ適合度 × 減衰」でスコア付与
export async function getRecommendations({ limit = 10 } = {}, { storage }) {
const weights = await tagWeights(storage);
const all = await fetchAllArticles();
return all
.filter(a => !storage.exists(a)) // 未読のみ
.map(a => {
const tagScore = a.tags.reduce((s, t) => s + (weights[t] || 0), 0);
const score = (tagScore || 1) * decay(a.publishedAt);
return { ...a, score };
})
.sort((a, b) => b.score - a.score)
.slice(0, limit);
}
なにをしているか
-
指数減衰 (decay)
新しい記事ほどスコアが高く、日数が経つと指数関数的に減衰 -
タグ重み (tagWeights)
ユーザが「★評価」した読了記事 100 件を対象に、タグ × 評価 を加算 -
スコア算出
未読記事に タグ適合度 × 減衰 を掛け合わせ、上位 N 件を返却。
タグが合わない場合でも減衰値だけで “純粋な新着度” を確保
4. デモ
4-1. 記事取得 → Notion 保存
ユーザー
今週のおすすめ記事を1件ずつストックして
今週のおすすめ記事を各ソースから1件ずつ、合計4件をNotionに正常にストックしました!
ストックした記事:
- Qiitaから:セキュリティ関連の記事
- Dev.toから:アイデア創出に関する記事
- NewsAPIから:Nintendoのゲームセールに関するニュース
- HackerNewsから:LLMとQ/kdb+プログラミングに関する技術記事
すべての記事が正常にNotionデータベースに同期されました。Notionで詳細を確認できます。
4-2. おすすめ記事を Notion DBの情報を参考に推薦
ユーザー
今までのストックに基づいておすすめ記事を推薦して
📝 あなたのストックに基づいて、おすすめの記事を推薦します!
-
AWS構成図作成の悩みを一掃!Diagram as Codeで始める"コードで描く"インフラ設計
👨💻 著者: k_adachi_01 (Qiita)
🏷️ タグ: AWS, diagram_as_code, 生成AI
📊 評価: 55 点 (いいね27, ストック14)
📅 公開日: 2025年7月9日 -
Claude 3.7 vs Gemini 2.5 pro for Coding
👨💻 著者: entelligenceai (Dev.to)
🏷️ タグ: webdev, programming, ai, javascript
📊 評価: 21 リアクション, 13 コメント
📅 公開日: 2025年7月7日 -
A Smarter Way to Auto-Generate Your Project Docs with AI
👨💻 著者: abubakersiddique771 (Dev.to)
🏷️ タグ: ai, chatgpt, gemini, deepseek
📊 評価: 25 リアクション
📅 公開日: 2025年7月7日
🚀 その他の注目記事
- Optimizing a Math Expression Parser in Rust — Rustでの数式パーサー最適化
- Is Gemini 2.5 good at bounding boxes? — AI画像認識の精度検証
- 国産の無料VPSを試す【Dify】 — 国産VPSサービスの実践レビュー
コミュニティ・ツール系
- Host Your Own Q&A Community Using Apache Answer — オープンソースQ&Aプラットフォーム
- スティーブ・ジョブズの「引き算の美学」 — デザイン思考とコミュニケーション
これらの記事は、あなたの過去のストック傾向に基づいて選ばれています。特に AI、プログラミング、AWS 関連の記事が多く推薦されていますね。
5. なぜ Notion 公式 MCP を採用しなかったか?
5-1. プロンプトの揺れを避けたい
-
公式 MCP はチャット側プロンプトで「テーブル定義取得 → レコード作成」を毎回明示する必要があり、
-
表現ゆらぎやスキーマ変更時の壊れリスクが高い
5-2. ストレージ多様化に備える
-
StoragePort抽象層によりアダプタ差し替え可能 -
公式 MCP 依存がないため、長期保守コストを低減
5-3. 開発速度を優先
-
notion-sdk-jsだけで CRUD が完結 -
ツール登録やスキーマ二重管理のコストを回避し、迅速に実装
6. まとめ & 次回予告
-
収集 → 要約 → 保存 → 推薦 のフロー完成
-
Phase 5 では
-
Slack Bot や Discord と 連携
-
cron / GitHub Actions で毎日自動同期
へ挑戦予定です
-
7. 参考文献
-
Notion API Official Docs — https://developers.notion.com/reference/intro
-
notion-sdk-js — https://github.com/makenotion/notion-sdk-js

