A temporary inbox for raw information before it's processed into an Obsidian vault.
This service is a buffer between raw sources (email, API, messages, etc) and a personal knowledge management system.
Think of it like a to-do list for information you want to process into a
Instead of directly processing incoming content into notes, this inbox:
- Receives raw information from multiple sources (email, API calls)
- Stores unprocessed items temporarily with their attachments
- Provides a simple API for clients to retrieve and process items
- Manages the lifecycle: unprocessed → processed → auto-deleted after 30 days
This separation allows for flexible processing workflows using different clients (Claude Desktop via MCP, custom scripts, etc.).
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