Content
# claw-ea
[English](README.en.md)
Doctors are too busy to organize information.
Messages from WeChat groups about surgical schedules, meeting notifications sent via WeChat, and various received files - glanced at and then pushed down by subsequent messages. By the time you need to use it, you've spent half a day flipping through chat records or simply forgotten.
I wrote claw-ea to solve this problem for myself: **Forward work messages to an AI assistant, which archives, builds calendars, and sets reminders for you.**
## Environment Requirements
> **The current version (v0.1.4.0) only runs on macOS and is designed for Chinese medical scenarios.**
| Condition | Description |
|------|------|
| **System** | macOS 13+ (Ventura and above) — Calendar and reminders use pyobjc EventKit, OCR uses macOS Vision |
| **Python** | 3.11+, using [uv](https://docs.astral.sh/uv/) to manage dependencies |
| **Obsidian** | Any version, notes are standard Markdown files |
| **MCP Client** | [OpenClaw](https://openclaw.com) (native plugin) or other MCP clients (Claude Desktop, Cursor, etc.) |
| **Conversion Tools** | [MinerU](https://github.com/opendatalab/MinerU) (required, main converter) + [docling](https://github.com/DS4SD/docling) (recommended, automatic fallback) + [markitdown](https://github.com/microsoft/markitdown) (recommended, Office/CSV fallback) |
Windows and Linux are not currently supported. We'll consider them if there's demand.
## What It Does
Forward work messages to OpenClaw, and claw-ea works in the background:
- **Save attachments** — Files are organized by date in the Obsidian attachment directory, skipping duplicates
- **Create notes** — Structured notes with frontmatter are generated in Obsidian, categorized by meetings, tasks, and files
- **Schedule calendar** — Meetings are written to Apple Calendar (with confirmation required)
- **Set reminders** — To-dos and agenda items you're responsible for are added to reminders
- **Image and PDF recognition** — Screenshots of schedules, notification images, and PDFs are directly read and summarized by AI multimodal vision, with the original file embedded as an attachment (`![[file]]`) in the note
- **Convert to Markdown** — Office documents like Word, Excel, and PPT are converted to Markdown and stored (using local offline MinerU, with docling and markitdown as fallbacks), making full-text search possible in Obsidian
All you need to do is forward.
## Scenarios
**Surgical schedule**: Forward schedule screenshots → AI reads all schedules → Your scheduled surgeries are automatically set as reminders based on time slots (1st surgery at 09:00, 2nd at 13:00, etc.)
**Meeting notifications**: Forward notifications → Create calendar events → Add reminders for agenda items you're responsible for
**Meeting minutes**: Forward minutes → Extract to-dos → Assign to you and set reminders → Add next meeting time to calendar
**Received files**: Forward images/PDFs → AI vision reads core content and writes it to notes, with the original file embedded; forward Word/Excel/PPT → MinerU converts to Markdown and embeds it in notes → Original file is kept as an attachment
Calendar and reminder writing require confirmation. Notes and attachments are stored directly with low risk and can be modified at any time.
## Technical Approach
claw-ea is a Python MCP server that runs as a native plugin on OpenClaw. Key design choices:
- **Tools only handle writing** (storing files, system API calls, and state reading) — Message classification, image understanding, and summary formatting are handled by LLM
- **MCP protocol** — Compatible with OpenClaw, Claude Desktop, Cursor, and other clients
- **Data stays local** — Sensitive medical information is not transmitted to any third party
- **pyobjc EventKit instead of AppleScript** — Handles Chinese surgical names with special characters, avoiding AppleScript escaping issues, and directly obtains event IDs and error messages
- **Portability and migration** — The project uses a `src/` layout, and the startup script uses relative paths for adaptation. Supports cross-directory migration by updating the gateway configuration path without modifying internal logic.
11 MCP tools: `save_attachment`, `convert_to_markdown`, `create_obsidian_note`, `create_calendar_event`, `delete_calendar_event`, `create_reminder`, `delete_reminder`, `ocr_image`, `detect_obsidian_vault`, `list_apple_calendars`, `save_config`
## Quick Start
```bash
git clone https://github.com/fshaan/claw-ea.git
cd claw-ea && uv sync
```
## Integrating with OpenClaw
claw-ea integrates with OpenClaw as a native plugin. The `openclaw-plugin/` directory contains a TypeScript bridge layer that registers Python MCP server tools with OpenClaw.
### Let AI Help You Install
Paste the following instructions into your OpenClaw agent, and it will install claw-ea:
<!-- AGENT INSTALL INSTRUCTIONS -->
```
Help me install the claw-ea plugin:
1. Clone the code and install dependencies:
cd ~/Workspace/devs && git clone https://github.com/fshaan/claw-ea.git claw_EA
cd claw_EA && uv sync
2. Install the OpenClaw plugin (included in the repository):
cp -r openclaw-plugin ~/.openclaw/extensions/claw-ea
cd ~/.openclaw/extensions/claw-ea && npm install
3. Register in ~/.openclaw/openclaw.json:
- Add "claw-ea" to "plugins.allow"
- Add to "plugins.entries":
"claw-ea": {
"enabled": true,
"config": {
"pythonPath": "<HOME>/Workspace/devs/claw_EA/.venv/bin/python",
"projectDir": "<HOME>/Workspace/devs/claw_EA"
}
}
- Add to "plugins.installs":
"claw-ea": {
"source": "path",
"installPath": "<HOME>/.openclaw/extensions/claw-ea",
"version": "<VERSION>"
}
Replace <HOME> with the actual path and <VERSION> with the content of the VERSION file (e.g., `cat VERSION`).
4. Create a configuration directory: mkdir -p ~/.claw-ea
Then create ~/.claw-ea/config.yaml with your username, vault path, calendar name, and reminder list.
Use the detect_obsidian_vault and list_apple_calendars tools to check available options.
5. **Configure agent behavior (required)**:
Read openclaw-plugin/PROMPT_TEMPLATE.md and append the AGENTS.md and TOOLS.md segments to ~/.openclaw/workspace/AGENTS.md and TOOLS.md, respectively.
If existing sections exist, replace them; if not, append them.
This step defines message classification rules and tool call, skipping it will cause workflow errors.
6. Restart OpenClaw: openclaw restart
```
<!-- END AGENT INSTALL INSTRUCTIONS -->
### Update Existing Installation
```
1. cd <project directory> && git pull
2. Copy plugin files:
cp openclaw-plugin/index.ts ~/.openclaw/extensions/claw-ea/index.ts
cp openclaw-plugin/src/tools.ts ~/.openclaw/extensions/claw-ea/src/tools.ts
3. Update ~/.openclaw/openclaw.json plugins.installs.claw-ea.version to the VERSION file content
4. Re-execute step 5 (read PROMPT_TEMPLATE.md and update AGENTS.md and TOOLS.md)
5. Restart OpenClaw: openclaw restart
```
### Manual Installation
1. Clone the code:
```bash
cd ~/Workspace/devs
git clone https://github.com/fshaan/claw-ea.git claw_EA
cd claw_EA && uv sync
```
2. Install the plugin:
```bash
cp -r openclaw-plugin ~/.openclaw/extensions/claw-ea
cd ~/.openclaw/extensions/claw-ea && npm install
```
3. Register in `~/.openclaw/openclaw.json` (three places: `plugins.allow`, `plugins.entries`, and `plugins.installs`)
4. Write the configuration file `~/.claw-ea/config.yaml` (see [Configuration](#configuration))
5. **Configure agent behavior (required)** — Read `openclaw-plugin/PROMPT_TEMPLATE.md` and append the AGENTS.md and TOOLS.md segments to ~/.openclaw/workspace/AGENTS.md and TOOLS.md, respectively. Skipping this step will cause classification rule loss.
6. `openclaw restart`
### MCPorter (for debugging)
MCPorter is an independent command-line debugging tool that directly calls MCP tools without registering with the OpenClaw agent.
```bash
# Add to ~/.mcporter/mcporter.json:
# "claw-ea": { "command": ".../.venv/bin/python", "args": ["-m", "claw_ea.server"], "cwd": "..." }
mcporter call claw-ea.detect_obsidian_vault
```
### Other MCP Clients
Claude Desktop, Cursor, or any MCP client using stdio can be used:
```json
{
"mcpServers": {
"claw-ea": {
"command": "/path/to/claw_EA/.venv/bin/python",
"args": ["-m", "claw_ea.server"],
"cwd": "/path/to/claw_EA"
}
}
}
```
## Configuration
Create `~/.claw-ea/config.yaml`:
```yaml
user:
name: Dr. Zhang # Used to match your name in schedules and agendas
aliases: [Dr. Zhang, Zhang] # English name, abbreviation
obsidian:
vault_path: ~/Obsidian/my-vault
notes_folder: Inbox/OpenClaw # Relative path under the vault
attachments:
base_path: ~/Obsidian/my-vault/attachments/OpenClaw
organize_by_date: true
apple:
calendar_name: Work # Must exist in Calendar app
reminder_list: OpenClaw # Must exist in Reminders app
categories:
surgery:
schedule_time_slots:
1: "09:00" # 1st surgery
2: "13:00" # 2nd surgery
3: "17:00" # 3rd surgery
4: "20:00" # 4th surgery (emergency/additional)
user_roles: [Lead Surgeon, Team Leader, Assistant]
```
After installation, use the `detect_obsidian_vault` and `list_apple_calendars` tools to check available vaults and calendars.
## Development
```bash
uv sync --dev
uv run pytest # Run all tests
uv run pytest -m "not macos" # Run tests excluding macOS API tests
```
Architecture and design decisions are in [CLAUDE.md](CLAUDE.md).
## About
This project was developed with AI:
- **f.sh** — Idea, medical workflow domain knowledge, design decisions, and code review
- **Claude (Anthropic)** — Architecture, coding, testing, and documentation
## License
[MIT](LICENSE)
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
Python tool for converting files and office documents to Markdown.
awesome-claude-skills
A curated list of awesome Claude Skills, resources, and tools for...
antigravity-awesome-skills
The Ultimate Collection of 130+ Agentic Skills for Claude...
claude-context-mode
claude-context-mode plugin reduces MCP context bloat, saving up to 99% of tokens.
context-mode
MCP is the protocol for tool access. We're the virtualization layer for context.