An inbox for my note taking system so that I can quickly flag things now and thoughtfully organize them later when I'm in the right headspace.
This service is a buffer between raw sources (email, API, messages, etc) and my personal knowledge management system (an Obsidian vault).
Instead of directly processing incoming content into notes, this inbox:
- Receives raw information from multiple sources (email, API calls, AI chats)
- Stores unprocessed items temporarily with their attachments
- Provides a simple API for clients to retrieve and process items
This separation allows me to capture freely in the moment, then process intentionally when I'm ready. And it's client agnostic - it can all be done via MCP or http, and capture can additionally be done by email.
Obsidian doesn't have a push-friendly API - you can't just send data to your vault from anywhere. Instead, you have to pull data into the vault from a client. Doing so requires a unified receptacle, that's this val!
See CLAUDE.md for AI assistant guidelines and PROJECT.md for detailed architecture.
-
Remix on Val.town
-
Run one-time setup
Run the one-time setup script to create the database table in your val.town sqlite.
-
Configure Environment Variables
In Val.town, set these secrets:
INBOX_API_TOKEN- Create a secure random token for API auth (via e.g.openssl rand -hex 32)INCOMING_EMAIL_ALLOWLIST- Comma-separated email addresses allowed to send records to the inbox (e.g.name@gmail.com,name@work.org)
-
Set up MCP Server (for Claude Desktop integration)
Create
~/Library/Application Support/Claude/claude_desktop_config.json:{ "mcpServers": { "inbox": { "command": "deno", "args": [ "run", "--allow-net", "--allow-env", "/path/to/inbox/localMcpServer.ts" ], "env": { "INBOX_API_URL": "https://your-username-httphandler.web.val.run", "INBOX_API_TOKEN": "your-api-token" } } } }Alternatively, use the published val URL:
"command": "deno", "args": [ "run", "--allow-net", "--allow-env", "https://esm.town/v/your-username/inbox/localMcpServer.ts" ]
- SQLite database via standard library
- Blob storage for binary attachments
- Email sending/receiving built-in
- HTTP endpoints for API access
- Cron scheduling for cleanup tasks
obsidian-inbox/
├── server/ # Core http server logic
├── mcp/ # Model Context Protocol server
├── emailHandler.ts # Val.town email trigger
├── httpHandler.ts # Val.town HTTP endpoint
├── cleanupCron.ts # Val.town cron job
├── localMcpServer.ts # Entry point for local MCP
└── apiClient.ts # HTTP client (used by MCP)
Via Email: Send email to your Val.town email address from an allowlisted sender. The email body and attachments are automatically saved.
Via HTTP API:
curl -X POST https://your-val.web.val.run/api/record \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "raw": "Content to process later", "subject": "Meeting notes", "from": "manual-entry", "date": "2025-10-21T10:00:00Z", "attachmentBlobIds": [] }'
With Claude Desktop (MCP): In Claude Desktop, ask:
- "What's in my inbox?"
- "Download the attachments from inbox item XYZ"
- "Mark inbox item ABC as processed"
With Custom Scripts:
# Get unprocessed items curl https://your-val.web.val.run/api/inbox \ -H "Authorization: Bearer YOUR_TOKEN" # Mark item as processed curl -X PATCH https://your-val.web.val.run/api/record/{id}/processed \ -H "Authorization: Bearer YOUR_TOKEN"
All endpoints require Authorization: Bearer YOUR_TOKEN header.
| Method | Path | Description |
|---|---|---|
GET | / | Health check (no auth required) |
GET | /api/inbox | Retrieve all unprocessed records |
POST | /api/record | Create new inbox record |
PATCH | /api/record/:id/processed | Mark record as processed |
GET | /api/record/:recordId/attachments | Get attachment metadata |
GET | /api/record/:recordId/attachments/:blobId | Download attachment file |
Schema Changes:
- Update
inboxRecordSchemainserver/InboxService.ts - Increment table name in
server/db.ts(e.g.,inbox_records_2) - Redeploy vals to Val.town
Adding Endpoints:
- Add route in
server/app.ts - Add auth middleware if needed
- Update this README
Adding MCP Tools:
- Create tool file in
mcp/tools/ - Register in
mcp/tools/index.ts - Test with Claude Desktop
- Simple buffer - Not a full app, just a temporary holding area
- Client-side processing - Complex logic lives in clients, not here
- Stateless - Each record is independent
- Val.town native - Leverage platform features over external services
- Fail-fast - Let errors bubble with context
- Send email with notes/attachments to Val.town address
- Email handler saves to inbox
- Ask Claude Desktop: "What's in my inbox?"
- Claude reads items, processes into Obsidian vault
- Claude marks items as processed
- Auto-deleted after 30 days
- POST content via HTTP API
- Poll
/api/inboxendpoint - Process items with your script
- PATCH to mark processed
- Auto-deleted after 30 days
Go nuts