Obsidian MCP for ChatGPT
by tony816
README.md
# Obsidian MCP for ChatGPT Web
This project connects an Obsidian vault to a ChatGPT custom MCP app through Cloudflare.
The recommended always-on, no-domain setup keeps one fixed ChatGPT URL and
continues working while the Windows PC is off:
```text
ChatGPT web
-> fixed Cloudflare Worker URL (*.workers.dev)
-> current Cloudflare quick tunnel on an OCI Always Free VM
-> filesystem MCP bridge on 127.0.0.1:8000
-> rclone OneDrive mount
-> OneDrive/Obsidian Vault
-> Windows Obsidian when the PC is online
```
The random `trycloudflare.com` origin can change after a reboot. A systemd
supervisor publishes the new origin to the Worker, so the `workers.dev` URL
saved in ChatGPT does not change. The original Windows launcher remains a
manual fallback.
## Modes
| Mode | Public URL | Authentication | ChatGPT setting |
| --- | --- | --- | --- |
| `worker-proxy` (recommended, no domain) | Fixed `*.workers.dev` URL | 256-bit secret URL path | None |
| `quick-tunnel` (fallback) | Changing `*.trycloudflare.com` URL | 256-bit secret URL path | None |
| `named-tunnel` (domain required) | Fixed custom hostname | Cloudflare Access OAuth plus origin JWT validation | OAuth |
The primary MCP transport is **Streamable HTTP** at `/mcp`. Legacy GET SSE remains available, but quick tunnels buffer it, so ChatGPT must use the URL ending in `/mcp`.
## Security properties
- The bridge listens only on loopback. The OCI VM requires no public inbound
application port; `cloudflared` makes an outbound-only connection.
- In `worker-proxy` and `quick-tunnel` modes, every MCP path is below `/t/<64-hex-secret>/`; other paths return `404`.
- The path comparison at the local bridge and the Worker administrator-token comparison are timing-safe.
- The Worker administrator route accepts only authenticated updates containing a valid `https://*.trycloudflare.com` origin.
- Local secrets are encrypted with Windows DPAPI in ignored
`config.local.json`; Cloudflare stores the Worker administrator token as a
Worker secret. On OCI, the two bridge environment files are root-owned,
group-readable only by the dedicated service user, and excluded from Git.
- `/healthz` is local-only. The Worker does not forward it.
The full MCP URL is a credential. Anyone who obtains it can use the vault tools, including write tools. Do not share it or commit it.
## Prerequisites for the Windows fallback and one-time Worker setup
- Windows PowerShell 5.1 or PowerShell 7
- Python 3.11+ and [`uv`](https://docs.astral.sh/uv/)
- Node.js and npm (for one-time Worker deployment)
- Obsidian with the Local REST API plugin
- [`cloudflared`](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/)
- A free Cloudflare account; no purchased domain is required for `worker-proxy`
Install the Python dependencies:
```powershell
uv sync
```
## Always-on OCI Free Tier setup
The deployed Linux layout, systemd units, OneDrive mount, recovery commands,
and free-tier constraints are documented in
[`OCI_ALWAYS_FREE_SETUP.md`](OCI_ALWAYS_FREE_SETUP.md). The relevant source
files are:
- `src/obsidian_chatgpt_bridge/filesystem_server.py` - direct vault backend
exposing the same 12 MCP tools without running the Obsidian desktop app.
- `deploy/oci/*.service` - OneDrive mount, MCP bridge, and tunnel units.
- `scripts/oci_tunnel_supervisor.py` - quick-tunnel restart and stable Worker
origin update.
The Windows task `Obsidian MCP ChatGPT` must remain disabled while OCI is the
primary host. Otherwise a Windows login could replace the Worker origin with a
PC-local tunnel.
## Windows fallback setup without a domain
1. Install the Obsidian Local REST API plugin if needed:
```powershell
.\scripts\install_obsidian_local_rest_api.ps1 -VaultPath "<VAULT_PATH>"
```
2. Deploy the stable Worker. The first run opens one Cloudflare authorization page:
```powershell
.\scripts\setup_stable_worker_proxy.ps1
```
3. Start and verify the full route:
```powershell
.\scripts\launch_servers.ps1
```
4. Optionally register automatic startup 30 seconds after Windows logon only
when Windows is the primary host:
```powershell
.\scripts\install_autostart_task.ps1
```
5. Create or update the ChatGPT custom app:
- MCP URL: the value printed by the launcher and stored in `runtime\last_chatgpt_mcp_url.txt`
- Authentication: **None**
The URL stays fixed across reboots. Do not enable the Windows logon task at the
same time as the OCI services.
## Status
```powershell
.\scripts\check_status.ps1
```
This checks the Windows fallback services, configured mode, fixed origin, and a
real public MCP initialize request. OCI service status is checked with the
commands in `OCI_ALWAYS_FREE_SETUP.md`.
## Other modes
For a temporary changing URL, set `mode` to `quick-tunnel` and run the launcher. After each tunnel restart, update ChatGPT from `runtime\last_chatgpt_mcp_url.txt`.
For a custom domain with per-user OAuth, follow [`CLOUDFLARE_ACCESS_SETUP.md`](CLOUDFLARE_ACCESS_SETUP.md), run `scripts\setup_cloudflare_access.ps1`, and set ChatGPT authentication to **OAuth**.
Never expose a bridge started with `-AuthMode disabled` through any public tunnel.
## Tests
```powershell
uv run python -m unittest discover -s tests -v
cd cloudflare\stable-proxy
npm test
npm run check
```
## Secret rotation
- Path secret: remove `pathSecretProtected` from `config.local.json`, switch temporarily to `quick-tunnel`, run the launcher once to generate a new secret, then rerun `setup_stable_worker_proxy.ps1`. Update ChatGPT with the new fixed URL path.
- Worker administrator token: rerun `setup_stable_worker_proxy.ps1`; the path secret is preserved and the administrator token is replaced.
- Named-tunnel credentials: rotate them in Cloudflare and rerun `setup_cloudflare_access.ps1`.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues