journal-mcp-server

journal-mcp-server

A reference MCP server that enables AI agents to read, write, search, and analyze personal journal entries with mood scores over HTTP, featuring OAuth 2.0 and a swappable storage backend.

Category
访问服务器

README

journal-mcp-server

A reference implementation of a remote MCP (Model Context Protocol) server extracted from a personal journaling app. It exposes journal read/write operations as typed tools that any MCP-compatible agent (Claude, GPT, etc.) can call over HTTP.

Built to demonstrate agent tool design, permission scoping, and OAuth 2.0 integration in a real-world single-user scenario.


What this is

The journaling app this was extracted from stores daily entries with a happiness score (1–10). This MCP layer lets an AI assistant — connected via claude.ai or Claude Desktop — read, write, and analyse those entries on behalf of the owner.

The interesting design challenges this solves:

  • One owner, one agent. No multi-tenancy required, but the auth model still uses proper OAuth 2.0 so it works with Claude's connector UI without any custom SDK.
  • Bearer token pinned to OAuth secret. The issued access_token is the same value as the bearer token the /mcp route checks, so the OAuth consent flow and the API auth layer are a single secret — no separate token store.
  • Stateless transport. Each HTTP request creates a fresh MCP session. No WebSocket, no persistent server-side session.
  • Storage abstracted behind an interface. The JournalStore interface lets you swap the backing store (in-memory → SQLite → Postgres) without touching the tool definitions.

Architecture

claude.ai / Claude Desktop
        │
        │  POST /mcp  (Bearer token)
        ▼
┌─────────────────────────────────────────┐
│  Express app                            │
│                                         │
│  mcpAuth middleware                     │  ← validates bearer token,
│      │                                  │    sets req.mcpUserId
│      ▼                                  │
│  handleMcpRequest()                     │  ← creates MCP session per request
│      │                                  │
│      ▼                                  │
│  McpServer (Streamable HTTP transport)  │
│      │                                  │
│      ▼                                  │
│  JournalStore interface                 │  ← swappable backing store
└─────────────────────────────────────────┘

OAuth endpoints (same server):
  GET  /.well-known/oauth-authorization-server  → RFC 8414 metadata
  GET  /oauth/authorize                         → consent page
  POST /oauth/authorize                         → issue auth code
  POST /oauth/token                             → exchange code for token

Tools

Tool Description
create_entry Create a journal entry for a given date (one per day). Returns an error if an entry already exists for that date.
list_recent_entries Return the N most recent entries, newest first.
get_entry Fetch a single entry by date (YYYY-MM-DD).
search_entries Case-insensitive keyword search across all entry content, newest first.
get_mood_summary Aggregate happiness scores across a date range — average, min, max, and a count by score tier (low/mid/high).

All tools are defined with Zod schemas so the MCP SDK generates accurate JSON Schema for the agent's tool-use call.


Auth model

Bearer token (primary)

Every POST /mcp request must include:

Authorization: Bearer <MCP_TOKEN>

On a 401 the server returns a WWW-Authenticate header pointing to the OAuth metadata URL, which allows MCP clients that support dynamic discovery to kick off the OAuth flow automatically.

OAuth 2.0 (for claude.ai connector UI)

Claude's connector UI only accepts OAuth credentials, not raw bearer tokens. This server implements a minimal Authorization Code flow (RFC 6749) with PKCE (RFC 7636) and server metadata (RFC 8414):

  1. Claude fetches /.well-known/oauth-authorization-server to discover endpoints.
  2. Claude redirects the user to /oauth/authorize — a consent page served by this server.
  3. The user clicks Allow. The server issues a one-time auth code (5-minute TTL).
  4. Claude exchanges the code at /oauth/token. The server validates PKCE and returns MCP_TOKEN as the access_token.
  5. Claude uses the token as a bearer token on all subsequent /mcp calls.

Credentials to enter in Claude's connector UI:

Field Value
OAuth Client ID claude (or whatever you set OAUTH_CLIENT_ID to)
OAuth Client Secret your MCP_TOKEN value
Remote MCP Server URL https://your-domain.com/mcp

Transport

Streamable HTTP (MCP spec §3.2) — the server creates a fresh StreamableHTTPServerTransport for every request. This is the simplest MCP transport: no WebSocket handshake, no persistent connection, works through any HTTP reverse proxy.


Running locally

# 1. Install dependencies
npm install

# 2. Configure secrets
cp .env.example .env
# Edit .env — set MCP_TOKEN, MCP_USER_EMAIL, OAUTH_CLIENT_ID

# 3. Start the dev server (auto-reloads on file changes)
npm run dev

The server starts on port 3000 by default. Test with:

# Should return 401 with WWW-Authenticate header
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'

# Should return tool list
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your MCP_TOKEN>" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'

# OAuth metadata
curl http://localhost:3000/.well-known/oauth-authorization-server

Swapping the backing store

The JournalStore interface in src/journalStore.ts is the only contract the MCP tools depend on. To use a real database:

  1. Implement JournalStore against your ORM or query builder of choice.
  2. Pass your implementation to handleMcpRequest(store, req, res) in src/server.ts.

The InMemoryJournalStore included here is suitable for local development and testing — data is lost on server restart.


Environment variables

Variable Required Description
MCP_TOKEN Bearer token for /mcp. Also issued as the OAuth access_token.
MCP_USER_EMAIL Owner identifier — used as the userId passed to JournalStore.
OAUTH_CLIENT_ID OAuth client_id (e.g. claude).
PORT optional HTTP port, defaults to 3000.

Related projects

  • Riley-Claude-Skills — Riley's versioned Claude Skills portfolio: reusable instruction sets for PM workflows, personal finance, and more.

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选