Local DevLog MCP
# Local DevLog MCP
Local DevLog MCP is a macOS-first, single-user MCP server that turns Git push attempts from multiple repositories into one reviewable daily development log. The MCP client supplies the AI; this project does not call an external LLM API or run a background daemon.
**Current release candidate: v0.5.0.** The implemented workflow is Git collection → AI-proposed Daily Draft → explicit approval → one Notion Work Log and one Apple Calendar all-day event per work date and timezone.
## How it works
```text
git push
→ fail-open pre-push hook (attempt signal only)
→ local atomic JSON storage
→ on-demand stdio MCP server
→ client LLM proposes one Daily Draft
→ user reviews and approves an exact version
→ separately confirmed Notion and/or Calendar publication
```
Push collection works while the MCP server is stopped. A captured event is never presented as proof that a push succeeded: later remote verification returns `REMOTE_MATCH`, `REMOTE_MISMATCH`, or `UNKNOWN`.
## Features
- Multiple Git repositories with safe, idempotent registration and removal.
- Existing `pre-push` hook protection and fail-open collection.
- Credential-redacted push-attempt metadata, deterministic IDs, writer locks, and atomic JSON replacement.
- Date and timezone-based Git activity queries with remote-state verification.
- Versioned Daily Drafts with optimistic edits, immutable approved versions, MCP Apps review UI, and Elicitation-first approval.
- Read-only Notion authentication/schema validation and retry-safe publication.
- One Repository-grouped Notion Work Log per `workDate + timezone`; selected Next Actions become individual Tasks.
- Swift EventKit bridge for one all-day Apple Calendar event per daily identity.
- Independent Notion and Calendar states, duplicate prevention, and partial-failure recovery.
Not implemented: Slack, KakaoTalk, a web UI, multi-user support, a background daemon, or embedded LLM calls.
## Requirements
- macOS 14 or newer
- Node.js 20.19 or newer
- pnpm 10.15.0
- Git
- Xcode Command Line Tools
- A stdio MCP client such as Codex, Claude Code, or Claude Desktop
- Optional: a Notion integration and writable Tasks/Work Logs databases
## Install
```bash
git clone https://github.com/Kyoungwoong/report_local_mcp.git
cd report_local_mcp
corepack enable
corepack prepare pnpm@10.15.0 --activate
pnpm install --frozen-lockfile
pnpm typecheck
pnpm test
pnpm build
```
The build produces `dist/index.js`, the self-contained MCP App, and an ad-hoc signed Calendar bridge. See [Installation](docs/installation.md) for the clean-install and upgrade checklist.
## Connect from Codex
Use absolute paths. `command -v node` prints the Node executable and `pwd` prints the checkout path.
```bash
codex mcp add local-devlog -- /absolute/path/to/node /absolute/path/to/report_local_mcp/dist/index.js
codex mcp list
```
Codex CLI and the Codex IDE extension share MCP configuration. In the TUI, run `/mcp`, then ask Codex to call `ping`; a healthy server returns `pong`. A project-scoped alternative is `.codex/config.toml`:
```toml
[mcp_servers.local-devlog]
command = "/absolute/path/to/node"
args = ["/absolute/path/to/report_local_mcp/dist/index.js"]
cwd = "/absolute/path/to/report_local_mcp"
```
ChatGPT web/desktop does not read local Codex MCP configuration. See the current [Codex MCP documentation](https://developers.openai.com/codex/extend/mcp).
## Connect from Claude
Claude Code:
```bash
claude mcp add --scope user local-devlog -- /absolute/path/to/node /absolute/path/to/report_local_mcp/dist/index.js
claude mcp list
```
Run `/mcp` inside Claude Code to inspect the connection and tools.
For a source checkout in Claude Desktop, edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"local-devlog": {
"command": "/absolute/path/to/node",
"args": [
"/absolute/path/to/report_local_mcp/dist/index.js"
]
}
}
}
```
Fully quit and reopen Claude Desktop, then inspect Local MCP servers/Connectors and call `ping`. Anthropic recommends packaged desktop extensions for one-click distribution; v0.5.0 is a clone-and-build source release, not an `.mcpb` package.
MCP Apps and native form Elicitation depend on host support. Every Tool still returns structured JSON and text fallback when the UI is unavailable.
## Register Git repositories
Build first because installed hooks use absolute paths to Node and `dist/git/hook-runner.js`:
```bash
pnpm run setup -- add /absolute/path/to/repository-one /absolute/path/to/repository-two
pnpm run setup -- list
pnpm run setup -- timezone Asia/Seoul
pnpm run setup -- remove /absolute/path/to/repository-one
```
Use `pnpm run setup`, including `run`: pnpm 10 reserves `pnpm setup` for pnpm itself.
Setup validates each Git repository and prevents duplicate registration. It respects repository-local `core.hooksPath`, refuses external/shared hook paths, and refuses to overwrite an existing `pre-push`. Removal verifies the exact installed hook hash and never deletes a modified or third-party hook. Moving this checkout or changing the Node executable requires removing and re-adding registered repositories.
## Configure Notion
Create a Notion internal integration, share the Tasks and Work Logs databases with it, and copy the example:
```bash
cp .env.example .env
```
```dotenv
NOTION_TOKEN=
NOTION_TASKS_DATABASE_ID=
NOTION_TASKS_DATA_SOURCE_ID=
NOTION_WORKLOGS_DATABASE_ID=
NOTION_WORKLOGS_DATA_SOURCE_ID=
```
Database IDs identify the parent containers; Data Source IDs identify the query/create targets in the current Notion API. Providing both is recommended. The loader also accepts one usable ID per target and reports legacy Database fields that contain Data Source IDs.
Required Tasks properties:
| Property | Type | Required option |
| --- | --- | --- |
| Name | title | — |
| Due Date | date | — |
| Local Id | rich_text | — |
| Status | select | TODO |
| Priority | select | MEDIUM |
Required Work Logs properties:
| Property | Type |
| --- | --- |
| Name | title |
| Date | date |
| Repository | url |
| Summary | rich_text |
| Local ID | rich_text |
Validate without writing:
```bash
pnpm notion:validate
```
The API version is pinned to `2026-03-11`. Validation never edits a schema or creates a page.
## Configure Apple Calendar
```bash
pnpm build
pnpm run setup -- calendar list
pnpm run setup -- calendar set <calendar-identifier>
```
`calendar list` is the explicit full-access permission request. Select only an existing writable Calendar; Local DevLog never creates, renames, or deletes a Calendar. If denied, enable access under **System Settings → Privacy & Security → Calendars** and retry.
The bridge is built from source and ad-hoc signed. Its Info.plist contains `NSCalendarsFullAccessUsageDescription`, and it targets macOS 14. Rebuilding after a code change may require permission again because an ad-hoc code identity is tied to that build. See [Installation](docs/installation.md) for signing and future notarized-binary requirements.
## Daily development log workflow
1. Ask the MCP client to call `get_daily_activity` for a real local date and summarize only the returned Git evidence.
2. Save the proposal with `save_daily_draft`, including its `sourceFingerprint` and source event IDs. Saving does not approve anything.
3. Review with `get_daily_draft` or `list_daily_drafts`; edit with `update_daily_draft` and the current `expectedVersion`.
4. Explicitly approve one `draftId` and `version` through `approve_daily_draft`.
5. Preview and separately authorize either external target.
Approved drafts are immutable. New Git activity after approval produces `sourceChangedAfterApproval`; v0.5.0 does not automatically amend already published records.
### Publish to Notion
1. Call `preview_notion_publication` with the approved version and zero-based `selectedNextActionIndexes`.
2. Review the single Work Log, selected Tasks, Local IDs, and `previewFingerprint`.
3. Explicitly confirm `publish_to_notion` with the same selection and fingerprint.
4. Check `get_notion_publication_status` and retry only failed items when necessary.
All Work Items are grouped by Repository in one Work Log body. Only selected Next Actions become Tasks. Approval alone never publishes.
### Publish to Apple Calendar
1. Optionally call `validate_calendar_connection` with `requestPermission: false`.
2. Call `preview_calendar_publication` for the exact approved version.
3. Review the Calendar, all-day date, body, Notion links, and `previewFingerprint`.
4. Explicitly confirm `publish_to_calendar` with the same fingerprint.
5. Check `get_calendar_publication_status`.
The event uses the Draft's IANA timezone and never treats Git timestamps as work hours. Notion and Calendar publication states are independent.
## Duplicate prevention
The daily identity is `workDate + timezone`, not the Draft ID. A day can have:
- one Notion Work Log containing every Repository's approved Work Items;
- one Apple Calendar all-day event;
- any explicitly selected Next Action Tasks.
Retrying the same Draft adopts or skips existing records. A different Draft for an already published daily identity returns `DAILY_PUBLICATION_CONFLICT`; Local DevLog never silently overwrites or deletes the existing record.
## Security and local data
The default data directory is:
```text
~/Library/Application Support/local-devlog-mcp/
```
It contains `config.json`, `events.json`, `drafts.json`, `notion-publications.json`, and `calendar-publications.json`. `LOCAL_DEVLOG_DATA_DIR` overrides this location for isolated tests. Files are written with restrictive permissions and atomic replacement; no Git diffs are stored.
The Notion token remains in the ignored `.env` file or process environment. Remote URLs and commit subjects are redacted for common credentials before persistence. stdio stdout is reserved for MCP protocol messages; diagnostics use stderr.
MCP Tools validate input with Zod and external writes require a persisted approved Draft, exact version, matching preview fingerprint, and a second confirmation. Native Elicitation is the strongest supported boundary. On clients without it, the exact-phrase fallback cannot prove human presence because an AI client can reproduce text; review the stored `approvalMethod` and enter publication confirmations yourself.
## Testing
```bash
pnpm install --frozen-lockfile
pnpm typecheck
pnpm test
pnpm build
pnpm audit --audit-level moderate
```
Normal tests use temporary Git repositories and mock Notion/EventKit adapters. They do not touch the user's repositories or external data. Read-only/live and write integrations are explicit opt-ins:
```bash
pnpm test:notion:integration
pnpm test:calendar:integration
# Do not run test:calendar:write without reviewing its required preview and confirmation.
```
## FAQ
- **Why is a successful `git push` not marked as proven?** The hook runs before Git knows the outcome. Later remote equality is evidence about current ref state, not proof of which command changed it.
- **Why did setup reject my hook?** Automatic chaining could change stdin and exit behavior, so existing hooks are protected.
- **Why is the MCP command silent?** A stdio server waits for a client; silence is expected.
- **Why did Calendar permission appear again?** The locally ad-hoc signed bridge changed after rebuilding.
- **Can the project update an already published day?** Not in v0.5.0; use a future explicit amendment workflow.
- **Where are detailed fixes?** See [Troubleshooting](docs/troubleshooting.md).
## Project status and license
See [Architecture](docs/architecture.md), [Roadmap](docs/roadmap.md), and [Changelog](CHANGELOG.md). Slack and KakaoTalk remain future ideas only.
Licensed under the MIT License; see [LICENSE](LICENSE).
TDQS
Scored across 15 tools
Each tool targets a distinct action and resource: draft lifecycle, Notion publication, Calendar publication, and connectivity. The parallel Notion and Calendar tools are clearly separated by platform, and draft read/list/save/update/approve/preview/publish boundaries are explicit.
Nearly all tools follow a predictable snake_case verb_noun pattern, with parallel naming for Notion and Calendar workflows. The only outlier is the simple connectivity tool `ping`, which is conventional and does not disrupt the pattern.
Fifteen tools are well scoped for a local devlog workflow involving draft revisions, approval, Notion publication, and Calendar publication. Each tool appears to earn its place by covering a distinct lifecycle step or integration check.
The surface covers the core daily-draft lifecycle and mirrors publication pipelines for both Notion and Calendar with validation, preview, publish, and status tools. A minor gap is the lack of explicit task selection/discovery tools despite preview referencing selected Tasks, and retry handling is only implied through status.