main() bound 0.0.0.0 unconditionally. That was defensible while the server
was an API for remote agents; now that /ui serves a browser console over the
whole vault, a bare `python -m obsidian_wiki.server` on a box with a public
address exposes it to the internet.
Default to 127.0.0.1 and read WIKI_HOST to override. A container has to
listen on every interface, so the Dockerfile now sets WIKI_HOST=0.0.0.0
explicitly — `docker run -p 8080:8080` behaves exactly as before.
Closes the loopback-by-default point raised in #208.
Everything else here is local: skills on your machine, a vault on your disk.
This puts a vault behind a URL so an agent elsewhere can search and write it.
One container, one vault, one API key. The vault stays plain markdown on a
mounted volume, so Obsidian still opens it. The container does no LLM work --
search and packing delegate to the existing graphrag/context_pack modules, and
the caller's agent does the thinking.
- obsidian_wiki/server.py: four vault functions, five REST routes and four MCP
tools as transport over them. Auth is one bearer key; the process refuses to
start without WIKI_API_KEY unless WIKI_ALLOW_ANONYMOUS=1. Every path is
resolved inside the vault or refused.
- Dockerfile, docker-compose.yml, .dockerignore, and a ghcr push on v* tags.
- New [server] extra; the core wheel stays dependency-free.
- docs/deployment.md, plus the WIKI_* vars in configuration.md and .env.example.
Requires mcp>=2.0: 2.0 renamed FastMCP to MCPServer, and session_manager only
exists once streamable_http_app() has been called -- a mounted sub-app's own
lifespan is ignored, so it is wired into the FastAPI lifespan by hand.