Obsidian MCP 服务器

通过OAuth和Cloudflare Tunnel实现安全的Obsidian笔记库远程访问,使AI助手能够随时随地读取和处理个人知识库。

  • by benpeter
  • TypeScript
  • 混合部署
  • 3 星标
  • 更新于
在 GitHub 查看 benpeter/obsidian-cloud-mcp

使用说明

Obsidian Cloud MCP

Access your Obsidian vault from Claude.ai on any device, including mobile, via an OAuth-protected MCP server running natively on a home Mac Studio.

What is this?

This repository provides the Cloudflare Worker OAuth layer and documentation for an Obsidian MCP setup. The MCP server, Cloudflare Tunnel ingress, and always-on configuration all run natively on a Mac Studio M1 (home, always-on), with no cloud server or Docker required.

The Problem: Obsidian runs locally, so AI assistants can't access your vault when you're on mobile or using cloud-based AI interfaces like Claude.ai.

The Solution: Run the MCP server natively on an always-on home Mac, expose it via a Cloudflare Tunnel, and protect it with an OAuth 2.1 provider on Cloudflare Workers.

Architecture

graph LR
    claude["claude.ai"] -->|"HTTPS"| cfedge["Cloudflare edge<br/>(TLS termination)"]
    cfedge -->|"tunnel"| cfd["cloudflared<br/>(LaunchDaemon, system)"]
    cfd -->|"http 127.0.0.1:8081"| prm["PRM responder<br/>(LaunchAgent, bp)"]
    cfd -->|"http 127.0.0.1:3000"| mcp["MCP server<br/>(LaunchAgent, bp)"]
    mcp -->|"http 127.0.0.1:27123"| obs["Obsidian.app (native)<br/>Local REST API plugin"]
    obs --> vault["/Users/bp/vault"]
    obs -->|"Obsidian Sync"| sync["other devices"]
    worker["Cloudflare Worker<br/>OAuth 2.1 + /introspect<br/>(UNCHANGED)"] -. "token introspection" .-> mcp
    cfedge -. "/.well-known/oauth-protected-resource" .-> worker

Detailed Component View

graph TB
    subgraph "User Devices"
        claude["Claude.ai<br/>(any device)"]
        browser["Browser<br/>(initial setup)"]
    end

    subgraph "Cloudflare Edge"
        worker["Cloudflare Worker<br/><b>OAuth Provider</b>"]
        kv["KV Store<br/>(tokens, clients)"]
        do["Durable Object<br/>(session state)"]
        worker --- kv
        worker --- do
    end

    subgraph github["GitHub"]
        gh_oauth["GitHub OAuth"]
    end

    subgraph "Mac Studio M1 (native, always-on)"
        cfd["cloudflared<br/>(LaunchDaemon, system)"]
        prm["PRM responder<br/>127.0.0.1:8081"]
        mcp["MCP server<br/>(benpeter/obsidian-mcp-server@92ebb79)<br/>127.0.0.1:3000"]
        obs["Obsidian.app<br/>+ Sync + Local REST API<br/>127.0.0.1:27123"]
        vault["/Users/bp/vault"]

        cfd -->|"/.well-known/..."| prm
        cfd -->|"/mcp"| mcp
        mcp -->|"REST API"| obs
        obs --- vault
    end

    claude -->|"1. MCP Request"| cfd
    cfd -->|"2. 401 + Resource Metadata"| claude
    claude -->|"3. OAuth Flow"| worker
    worker -->|"4. GitHub Login"| gh_oauth
    gh_oauth -->|"5. Token"| worker
    worker -->|"6. Access Token"| claude
    claude -->|"7. MCP + Bearer Token"| cfd
    mcp -->|"8. Validate Token"| worker

    style worker fill:#f59e0b,color:#000
    style mcp fill:#7c3aed,color:#fff
    style obs fill:#7c3aed,color:#fff
    style cfd fill:#22c55e,color:#000

Authentication Flow (RFC 7662 Token Introspection)

The MCP server and OAuth server are on separate hosts. Claude.ai discovers the OAuth server via Protected Resource Metadata (RFC 9728), then authenticates via GitHub OAuth on Cloudflare. The MCP server validates tokens by calling Cloudflare's introspection endpoint.

sequenceDiagram
    participant C as Claude.ai
    participant M as Mac Studio<br/>(MCP Server)
    participant CF as Cloudflare<br/>(OAuth Provider)
    participant GH as GitHub<br/>(Identity)

    Note over C: User adds MCP connector
    C->>M: POST /mcp (no token)
    M-->>C: 401 Unauthorized

    C->>M: GET /.well-known/oauth-protected-resource
    M-->>C: {"authorization_servers": ["cloudflare-worker-url"]}

    C->>CF: GET /.well-known/oauth-authorization-server
    CF-->>C: {endpoints...}

    C->>CF: POST /register (Dynamic Client Registration)
    CF-->>C: {client_id, client_secret}

    C->>CF: GET /authorize (+ PKCE)
    CF->>GH: GitHub OAuth redirect
    GH-->>CF: Authorization code
    Note over CF: Verify email in whitelist
    CF-->>C: Authorization code

    C->>CF: POST /token (code + code_verifier)
    CF-->>C: Access token (opaque)

    Note over C: MCP connection established
    C->>M: POST /mcp + Bearer token
    M->>CF: POST /introspect (token)
    CF-->>M: {"active": true, "sub": "..."}
    M-->>C: MCP response (tools, resources)

Components

Mac Studio (native)

Component Purpose Bind
cloudflared Cloudflare Tunnel ingress, TLS at edge system LaunchDaemon
MCP server Obsidian MCP with Token Introspection 127.0.0.1:3000 (LaunchAgent, bp)
PRM responder Serves /.well-known/oauth-protected-resource 127.0.0.1:8081 (LaunchAgent, bp)
Obsidian.app Vault + Sync + Local REST API plugin 127.0.0.1:27123 (login item, bp)

The MCP server is benpeter/obsidian-mcp-server at commit 92ebb79 (a fork of cyanheads/obsidian-mcp-server carrying RFC 7662 Token Introspection support). The source is vendored at studio/mcp-server-src/.

Obsidian runs as a native app (not headless/Docker), against the real vault at /Users/bp/vault. Auto-login (bp) and launchd ensure the endpoint recovers unattended after reboot or power loss.

Cloudflare Worker

Endpoint Purpose
/.well-known/oauth-authorization-server OAuth discovery (RFC 8414)
/.well-known/oauth-protected-resource Resource metadata (RFC 9728)
/authorize OAuth authorization
/callback GitHub OAuth callback
/token Token exchange
/register Dynamic client registration (RFC 7591)
/introspect Token introspection (RFC 7662)

MCP Server Environment

Variable Description
MCP_AUTH_MODE introspection — validates tokens via remote endpoint
TOKEN_INTROSPECTION_URL URL of the Cloudflare /introspect endpoint
OBSIDIAN_API_KEY Local REST API plugin key
OBSIDIAN_BASE_URL http://127.0.0.1:27123
MCP_TRANSPORT_TYPE http — Streamable HTTP transport
MCP_HTTP_HOST 127.0.0.1 (tunnel is local; not exposed to LAN)
MCP_HTTP_PORT 3000

Quick Start

Step 1: Cloudflare Worker Setup

The Cloudflare Worker acts as OAuth provider for Claude.ai.

  1. Create a GitHub OAuth App:

  2. Deploy the Worker:

    cd cloudflare-mcp-server
    npm install
    npx wrangler login
    
    # Create KV namespace
    npx wrangler kv namespace create OAUTH_KV
    
    # Update wrangler.jsonc with the KV namespace ID
    
    # Set secrets
    npx wrangler secret put GITHUB_CLIENT_ID
    npx wrangler secret put GITHUB_CLIENT_SECRET
    npx wrangler secret put COOKIE_ENCRYPTION_KEY  # openssl rand -base64 32
    
    # Deploy
    npx wrangler deploy
    
  3. Update GitHub OAuth App callback URL with the deployed worker URL.

Step 2: DNS

Create a CNAME pointing your subdomain at the Cloudflare Tunnel:

cloudflared tunnel create obsidian-mcp-studio
cloudflared tunnel route dns obsidian-mcp-studio mcp.yourdomain.com

(Requires the domain to be hosted on Cloudflare DNS.)

Step 3: Mac Studio Setup

See studio/README.md for the full native setup runbook:

  • Install and configure cloudflared as a system LaunchDaemon
  • Build and deploy the MCP server as a LaunchAgent
  • Configure the PRM responder LaunchAgent
  • Set up Obsidian auto-launch and Local REST API plugin
  • Enable auto-login for always-on recovery

Step 4: Configure Claude.ai

In Claude.ai settings, add a custom MCP connector:

Field Value
Server URL https://obsidian-mcp.mostly-hallucinations.com/mcp

Claude.ai will automatically:

  1. Discover the OAuth server via Protected Resource Metadata
  2. Redirect you to GitHub for login
  3. Establish the MCP connection after successful auth

Email Whitelist

Access is restricted by GitHub email. The allowed email is configured in cloudflare-mcp-server/src/github-handler.ts:

const ALLOWED_EMAILS = new Set<string>(["your-email@example.com"]);

Security

Authentication

Layer Method Details
MCP Server OAuth 2.1 Via Cloudflare Worker, tokens validated via RFC 7662 Introspection
OAuth Identity GitHub OAuth Email whitelist restricts access

Network

  • MCP only via HTTPS — Cloudflare Tunnel with TLS at the edge
  • REST API loopback-only — Port 27123 bound to 127.0.0.1, not exposed to LAN
  • MCP server loopback-only — Port 3000 bound to 127.0.0.1
  • No inbound ports — Cloudflare Tunnel is outbound-only; no port-forwarding required

HTTPS

  • Automatic certificates managed by Cloudflare (CF-managed TLS on the edge)
  • No Let's Encrypt, no port 80/443 inbound on the Mac

Troubleshooting

MCP server returning 401:

  • Token introspection might be failing
  • Check MCP logs: /Users/bp/obsidian-mcp/logs/mcp.err.log
  • Verify Cloudflare Worker is deployed and /introspect endpoint works

Tunnel not connecting:

  • Check cloudflared logs: /Library/Logs/com.benpeter.cloudflared.err.log
  • Restart: sudo launchctl kickstart -k system/com.benpeter.cloudflared

OAuth redirect errors:

  • Verify GitHub OAuth App callback URL matches worker URL
  • Check email whitelist in github-handler.ts

Obsidian REST API not responding:

  • Confirm Obsidian.app is running: curl -s http://127.0.0.1:27123/
  • Check that the Local REST API plugin is enabled and bound to 127.0.0.1

See studio/README.md for full restart and health-check commands.

Deployment

There is no IaC or GitHub Actions deployment for the Mac Studio setup — it's a hand-managed home machine. The setup runbook and ops reference are in studio/README.md.

The Cloudflare Worker is deployed manually via wrangler deploy from cloudflare-mcp-server/ (see Quick Start above).

Costs

Component Monthly Cost
Cloudflare Worker Free tier
Domain (mostly-hallucinations.com) ~$1
Obsidian Sync $4-8
Mac Studio (owned hardware) $0 incremental
Total ~$5-9/month

Repository Structure

obsidian-cloud-mcp/
+-- cloudflare-mcp-server/   # Cloudflare Worker (OAuth + Introspection)
|   +-- src/
|   |   +-- index.ts                    # MCP proxy + OAuthProvider
|   |   +-- github-handler.ts           # GitHub OAuth + email whitelist + /introspect
|   |   +-- utils.ts                    # OAuth helpers
|   |   +-- workers-oauth-utils.ts      # CSRF, state management
|   +-- wrangler.jsonc                  # Cloudflare config
+-- studio/                  # Native Mac Studio deployment
|   +-- README.md                       # Setup runbook and ops reference
|   +-- mcp-server-src/                 # Vendored MCP server source (benpeter/obsidian-mcp-server@92ebb79)
+-- docs/                    # Design documents
|   +-- migration/
|       +-- 2026-05-29-mac-studio-migration-design.md
+-- mcp-server/              # Smart-server WIP (not deployed)
+-- LICENSE

License

Apache 2.0 — see LICENSE