• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
drewmcdonald

drewmcdonald

inbox

Public
Like
inbox
Home
Code
13
mcp
2
server
5
.vtignore
CLAUDE.md
PROJECT.md
README.md
apiClient.ts
C
cleanupCron.ts
deno.json
E
emailHandler.ts
H
httpHandler.ts
localMcpServer.ts
onetimeSetup.ts
Branches
1
Pull requests
Remixes
History
Environment variables
2
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
10/21/2025
Viewing readonly version of main branch: v321
View latest version
README.md

Inbox =>

A temporary inbox for raw information before it's processed into an Obsidian vault.

Why This Exists

My "capture" mindset is different from my "organize" mindset.

When I'm capturing information—forwarding an email, saving a link, jotting down a thought—I'm in flow. I don't want to stop and think about where it belongs in my PKM system, what tags it needs, or how to structure it as a proper note.

But I also don't want to just fire random shit directly into my carefully organized Obsidian vault.

This inbox solves that tension. It's a holding area where I can quickly flag things now and thoughtfully organize them later when I'm in the right headspace.

What is this?

This service is a buffer between raw sources (email, API, messages, etc) and your personal knowledge management system.

Instead of directly processing incoming content into notes, this inbox:

  1. Receives raw information from multiple sources (email, API calls)
  2. Stores unprocessed items temporarily with their attachments
  3. Provides a simple API for clients to retrieve and process items
  4. Manages the lifecycle: unprocessed → processed → auto-deleted after 30 days

This separation allows you to capture freely in the moment, then process intentionally when you're ready—using different clients (Claude Desktop via MCP, custom scripts, etc.).

Quick Start

See CLAUDE.md for AI assistant guidelines and PROJECT.md for detailed architecture.

Setup

  1. Remix on Val.town

  2. Run one-time setup

    Run the one-time setup script to create the database table in your val.town sqlite.

  3. 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)
  4. 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" ]

Architecture

Platform: Val.town Serverless

  • 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

File Organization

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)

Usage

Sending Content to Inbox

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": [] }'

Processing Inbox Items

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"

API Reference

All endpoints require Authorization: Bearer YOUR_TOKEN header.

Endpoints

MethodPathDescription
GET/Health check (no auth required)
GET/api/inboxRetrieve all unprocessed records
POST/api/recordCreate new inbox record
PATCH/api/record/:id/processedMark record as processed
GET/api/record/:recordId/attachmentsGet attachment metadata
GET/api/record/:recordId/attachments/:blobIdDownload attachment file

Making Changes

Schema Changes:

  1. Update inboxRecordSchema in server/InboxService.ts
  2. Increment table name in server/db.ts (e.g., inbox_records_2)
  3. Redeploy vals to Val.town

Adding Endpoints:

  1. Add route in server/app.ts
  2. Add auth middleware if needed
  3. Update this README

Adding MCP Tools:

  1. Create tool file in mcp/tools/
  2. Register in mcp/tools/index.ts
  3. Test with Claude Desktop

Design Philosophy

  1. Simple buffer - Not a full app, just a temporary holding area
  2. Client-side processing - Complex logic lives in clients, not here
  3. Stateless - Each record is independent
  4. Val.town native - Leverage platform features over external services
  5. Fail-fast - Let errors bubble with context

Common Workflows

Email → Claude Processing

  1. Send email with notes/attachments to Val.town address
  2. Email handler saves to inbox
  3. Ask Claude Desktop: "What's in my inbox?"
  4. Claude reads items, processes into Obsidian vault
  5. Claude marks items as processed
  6. Auto-deleted after 30 days

API → Custom Script

  1. POST content via HTTP API
  2. Poll /api/inbox endpoint
  3. Process items with your script
  4. PATCH to mark processed
  5. Auto-deleted after 30 days

License

Go nuts

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.