MCP test add worklog.md

This commit is contained in:
president
2026-02-07 19:27:53 +09:00
parent 4a93fb8260
commit a8957742ea
6 changed files with 258 additions and 0 deletions

24
.cursor/rules.md Normal file
View File

@@ -0,0 +1,24 @@
# Cursor Rules: 開発日記dev_diary
## 目的
ユーザーが「開発日記に書いといて」と言ったら、要約・タグ付け・メタデータ補完を行い、MCP の `diary_upsert``dev_diary` に保存する。
## 保存ルール
- ツール: `diary_upsert`
- collection: `dev_diary`
- content: 1〜4文で要約実作業が分かる具体性
- tags: 2〜5個下記候補から選び、足りなければ追加
- topic: 1語下記候補、なければ `general`
- source: `codex`
- author: 未指定なら自動補完に任せる
- ts: 未指定なら自動補完に任せる
## タグ候補
`pgvecter`, `mcp`, `api`, `deploy`, `ops`, `security`, `db`, `migration`, `embedding`, `search`, `bugfix`, `refactor`, `docs`, `test`
## トピック候補
`api`, `mcp`, `deploy`, `ops`, `security`, `db`, `docs`, `test`, `general`
## 例
ユーザー: 「開発日記に書いといて。今日は削除API追加と監査ログ導入、テストまで完了。」
`diary_upsert` で content を要約し、tags に `api`, `mcp`, `deploy` などを付与して保存。

1
.cursor/worklog.md Normal file
View File

@@ -0,0 +1 @@
# 作業日誌

9
.githooks/post-commit Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"
if [[ -x "scripts/worklog_mcp.sh" ]]; then
scripts/worklog_mcp.sh || true
fi

3
.gitignore vendored
View File

@@ -176,3 +176,6 @@ cython_debug/
# macOS
.DS_Store
# worklog MCP hook state
.worklog_mcp_state

View File

@@ -427,6 +427,25 @@ curl -s http://127.0.0.1:8092/health
- `diary_upsert``content_hash` は本文 (`content`) を trim & LF 正規化して SHA-256 を計算し、`sha256:<hex>` で保存
- `*_search_by_id``metadata.id``eq` で検索するショートカット
## MCP 運用ルール(開発日記)
Cursor などの指示ファイルに以下の運用ルールを設定しておくと、会話だけで日記が回せる。
### ルール概要
- ツール: `diary_upsert`
- collection: `dev_diary`
- content: 1〜4文で要約実作業が分かる具体性
- tags: 2〜5個候補から選ぶ
- topic: 1語候補から選ぶ、なければ `general`
- source: `codex`
- author/ts: 未指定なら自動補完
### タグ候補
`pgvecter`, `mcp`, `api`, `deploy`, `ops`, `security`, `db`, `migration`, `embedding`, `search`, `bugfix`, `refactor`, `docs`, `test`
### topic 候補
`api`, `mcp`, `deploy`, `ops`, `security`, `db`, `docs`, `test`, `general`
### 例: /kb/search
```bash

202
scripts/worklog_mcp.sh Executable file
View File

@@ -0,0 +1,202 @@
#!/usr/bin/env bash
set -euo pipefail
WORKLOG_PATH="notes/worklog.md"
STATE_PATH=".worklog_mcp_state"
MCP_SERVER_CMD=(go run /Users/sunamurahideyuki/develop/pgvecterAPI/cmd/mcp-server)
if [[ ! -f "$WORKLOG_PATH" ]]; then
exit 0
fi
# Extract the last paragraph (separated by blank lines)
entry="$(awk 'BEGIN{RS=""; ORS=""} {block=$0} END{print block}' "$WORKLOG_PATH" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
if [[ -z "$entry" ]]; then
exit 0
fi
summary="$(WORKLOG_ENTRY="$entry" python3 - <<'PY'
import os, re
text = os.environ["WORKLOG_ENTRY"]
def summarize(t: str) -> str:
t = t.strip()
if not t:
return t
if "。" in t:
parts = [p for p in t.split("。") if p.strip()]
return "。".join(parts[:2]) + ("。" if len(parts) > 0 else "")
if "." in t:
parts = [p for p in t.split(".") if p.strip()]
return ".".join(parts[:2]) + ("." if len(parts) > 0 else "")
if len(t) > 240:
return t[:240].rstrip() + "..."
return t
print(summarize(text))
PY
)"
hash="$(printf "%s" "$entry" | shasum -a 256 | awk '{print $1}')"
if [[ -f "$STATE_PATH" ]]; then
last_hash="$(cat "$STATE_PATH" 2>/dev/null || true)"
if [[ "$hash" == "$last_hash" ]]; then
exit 0
fi
fi
if [[ -f ".env" ]]; then
set -a
# shellcheck disable=SC1091
. ./.env
set +a
fi
if [[ -z "${PGVECTER_BASE_URL:-}" || -z "${PGVECTER_API_KEY:-}" ]]; then
echo "worklog_mcp: PGVECTER_BASE_URL / PGVECTER_API_KEY が未設定のため送信をスキップしました。" >&2
exit 0
fi
has_cmd() {
command -v "$1" >/dev/null 2>&1
}
contains() {
local pattern="$1"
if has_cmd rg; then
printf "%s" "$entry" | rg -q "$pattern"
else
printf "%s" "$entry" | grep -Eq "$pattern"
fi
}
tags=()
add_tag() {
local t="$1"
for e in "${tags[@]}"; do
if [[ "$e" == "$t" ]]; then
return 0
fi
done
tags+=("$t")
}
contains "pgvecter|pgvecterAPI" && add_tag "pgvecter"
contains "MCP|mcp" && add_tag "mcp"
contains "API|api" && add_tag "api"
contains "デプロイ|deploy|リリース" && add_tag "deploy"
contains "運用|ops|監視" && add_tag "ops"
contains "セキュリティ|security" && add_tag "security"
contains "DB|db|database|マイグレーション|migration" && add_tag "db" && add_tag "migration"
contains "埋め込み|embedding" && add_tag "embedding"
contains "検索|search" && add_tag "search"
contains "バグ|bug" && add_tag "bugfix"
contains "リファクタ|refactor" && add_tag "refactor"
contains "ドキュメント|docs" && add_tag "docs"
contains "テスト|test" && add_tag "test"
if [[ "${#tags[@]}" -lt 2 ]]; then
add_tag "pgvecter"
add_tag "ops"
fi
if [[ "${#tags[@]}" -gt 5 ]]; then
tags=("${tags[@]:0:5}")
fi
topic="general"
if contains "MCP|mcp"; then
topic="mcp"
elif contains "デプロイ|deploy|リリース"; then
topic="deploy"
elif contains "運用|ops|監視"; then
topic="ops"
elif contains "セキュリティ|security"; then
topic="security"
elif contains "DB|db|database|マイグレーション|migration"; then
topic="db"
elif contains "ドキュメント|docs"; then
topic="docs"
elif contains "テスト|test"; then
topic="test"
elif contains "API|api"; then
topic="api"
fi
if has_cmd uuidgen; then
entry_id="$(uuidgen | tr '[:upper:]' '[:lower:]')"
else
entry_id="$(python3 - <<'PY'
import uuid
print(str(uuid.uuid4()))
PY
)"
fi
tags_joined=""
if [[ "${#tags[@]}" -gt 0 ]]; then
tags_joined="$(IFS="::"; echo "${tags[*]}")"
fi
export WORKLOG_ENTRY="$entry"
export WORKLOG_SUMMARY="$summary"
export WORKLOG_TAGS="$tags_joined"
export WORKLOG_TOPIC="$topic"
export WORKLOG_ID="$entry_id"
payload="$(python3 - <<'PY'
import json, os
entry = os.environ["WORKLOG_ENTRY"]
tags_raw = os.environ.get("WORKLOG_TAGS", "")
tags = tags_raw.split("::") if tags_raw else []
topic = os.environ["WORKLOG_TOPIC"]
entry_id = os.environ["WORKLOG_ID"]
init = {
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {"name": "worklog-hook", "version": "0.1"}
}
}
metadata = {"worklog_path": "notes/worklog.md"}
if entry != os.environ["WORKLOG_SUMMARY"]:
metadata["original"] = entry
call = {
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "diary_upsert",
"arguments": {
"id": entry_id,
"collection": "dev_diary",
"content": os.environ["WORKLOG_SUMMARY"],
"tags": tags,
"topic": topic,
"source": "codex",
"metadata": metadata
}
}
}
print(json.dumps(init))
print(json.dumps(call))
PY
)"
response="$(printf "%s\n" "$payload" | "${MCP_SERVER_CMD[@]}")"
if printf "%s" "$response" | grep -q '"isError":true'; then
echo "worklog_mcp: MCP 送信に失敗しました。" >&2
echo "$response" >&2
exit 0
fi
echo "$hash" > "$STATE_PATH"