Skip to main content
Glama
README.md
# graindrop

Audio capture pipeline. Listens for audio files, transcribes via whisper.cpp, and serves audio + transcript through an MCP server.

```
Audio file → graindrop → whisper.cpp → manifest.json → MCP server (:8648)
```

Any MCP-compatible agent (Hermes, Claude Code, Cursor, etc.) connects to the graindrop MCP and discovers new recordings as they land.

## One-sentence pitch

A self-contained daemon that watches a directory, transcribes anything that lands in it, and presents the results to any AI agent through a standard protocol — no cloud, no subscriptions, no vendor lock-in.

## How it works

1. Drop an audio file (`.m4a`, `.wav`, `.mp3`) into the watched directory
2. graindrop copies it to `audio/`, transcribes via whisper.cpp to `transcripts/`, archives the original to `_archive/`, and logs it in `manifest.json`
3. The MCP server exposes the recording to any connected agent through tools and resources
4. The agent reads the transcript, fetches the audio, and does what it does

## Quick start

```bash
# Install
pip install graindrop
# or from source:
git clone https://github.com/stuartmhannon/graindrop
cd graindrop
pip install -e .

# Start the MCP server
graindrop-mcp --port 8648

# The server watches ~/Dropbox/graindrop/ by default
# Drop an .m4a in there and the MCP server picks it up
```

## MCP Tools

| Tool | Purpose |
|---|---|
| `graindrop_list` | List all recordings, newest first |
| `graindrop_list_unread` | List only unacknowledged recordings |
| `graindrop_get_transcript` | Full transcript text for a recording |
| `graindrop_get_audio` | Audio file path for a recording |
| `graindrop_ack` | Mark a recording as read |
| `graindrop_stats` | Summary counts |

## MCP Resources

| URI | Content |
|---|---|
| `graindrop://recording/{id}/transcript` | Plain text transcript |
| `graindrop://recording/{id}/audio` | Binary audio (m4a/wav) |

## Configuration

```bash
graindrop-mcp --port 8648 --dir ~/grain/reference/graindrop
```

- `--port`: HTTP SSE port (default: 8648)
- `--dir`: Data directory (default: `~/grain/reference/graindrop`)

The watched directory defaults to `~/Dropbox/graindrop/`. Override by editing `WATCH_DIR` in `graindrop_mcp.py`.

## Storage layout

```
~/grain/reference/graindrop/
├── audio/{slug}.{ext}       ← canonical audio copy
├── transcripts/{slug}.txt   ← whisper transcript
├── _archive/{original}      ← source file backup
├── manifest.json            ← searchable index
├── graindrop_mcp.py         ← MCP server
├── graindrop_watcher.py     ← processing script
```

## Requirements

- Python 3.10+
- [whisper.cpp](https://github.com/ggerganov/whisper.cpp) (for transcription)
- ffmpeg (for audio conversion)
- `mcp[cli]` (installed automatically)

## Agent integration

### Hermes Agent

Add to `~/.hermes/config.yaml`:

```yaml
mcp_servers:
  graindrop:
    url: http://127.0.0.1:8648/sse
    transport: sse
```

### Any MCP client

Connect to `http://127.0.0.1:8648/sse` using the MCP protocol's HTTP SSE transport. Call `tools/list` to discover available tools, then `tools/call` to invoke them.

## License

MIT — do what you want, just don't blame us.