Commit Graph

8 Commits

Author SHA1 Message Date
8a90e78016 feat: full CRUD API + MCP tools for thoughts
Some checks failed
ci/woodpecker/push/build Pipeline failed
REST endpoints:
  GET    /v1/thoughts              — list with ?source=, ?metadata_id=, ?limit=, ?offset=
  GET    /v1/thoughts/{id}         — get by UUID (404 if not found)
  PATCH  /v1/thoughts/{id}         — update content/metadata, re-embeds if content changes
  DELETE /v1/thoughts/{id}         — delete by UUID (204 / 404)
  DELETE /v1/thoughts              — bulk delete by ?source= and/or ?metadata_id=

MCP tools (mirrors REST):
  get(thought_id)
  update(thought_id, content, metadata)
  delete(thought_id)
  delete_where(source, metadata_id)
  list_thoughts(source, metadata_id, limit, offset)

Internal refactor:
  - _row_to_thought() helper eliminates repeated Thought construction
  - UpdateRequest model with all-optional fields (PATCH semantics)
  - UUID validation on all by-id operations returns 404 cleanly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 20:36:42 -06:00
c02d1d8974 fix: configure MCP transport security with env-driven allowed hosts
All checks were successful
ci/woodpecker/push/build Pipeline was successful
FastMCP auto-enables DNS rebinding protection when host=127.0.0.1
(the default). Production requests from brain.woltje.com were rejected
with 421 Invalid Host header because the allowed_hosts list was empty.

Added MCP_ALLOWED_HOSTS config field (comma-separated). When set,
DNS rebinding protection is enabled with those hosts; when empty,
protection is disabled. Set MCP_ALLOWED_HOSTS=brain.woltje.com in
Portainer stack env.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 19:14:32 -06:00
679fda8491 fix: initialize MCP session_manager in lifespan and fix mount path
All checks were successful
ci/woodpecker/push/build Pipeline was successful
StreamableHTTPSessionManager requires its run() context manager to be
active before handling requests. Without it, every MCP call returned
RuntimeError: Task group is not initialized.

Also changed mount from /mcp to / (at end of route list) so the MCP
endpoint is accessible at /mcp rather than /mcp/mcp, matching the
sub-app's internal route structure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 19:11:48 -06:00
6818da489e fix: accept DATABASE_URL directly, add POSTGRES_PASSWORD to required vars
All checks were successful
ci/woodpecker/push/build Pipeline was successful
brain-api now takes DATABASE_URL as a complete connection string from env
instead of constructing it from POSTGRES_PASSWORD. This matches Portainer's
env var pattern and avoids password duplication.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:57:18 -06:00
1f0bb90964 fix: use correct Traefik label pattern for this cluster
All checks were successful
ci/woodpecker/push/build Pipeline was successful
TLS terminates at Cloudflare/pfSense, not Traefik.
Confirmed by inspecting working services (nextcloud, sage-phr):
- entrypoints=web (not websecure)
- no tls or certresolver labels needed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:51:39 -06:00
f33d4a57a3 fix: resolve lint errors — import ordering, line length
All checks were successful
ci/woodpecker/push/build Pipeline was successful
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:30:12 -06:00
3c168e849a ci: fix woodpecker pipeline — kaniko pattern matching mosaic-stack
Some checks failed
ci/woodpecker/push/build Pipeline failed
- Switch from plugins/kaniko to gcr.io/kaniko-project/executor:debug
- Use gitea_username/gitea_token secret names (matches org pattern)
- Use YAML anchor for docker config setup
- Fix image destination to use shell variable (YAML anchors don't expand in commands)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:28:29 -06:00
5771ec5260 feat: initial alpha scaffold — FastAPI + MCP + pgvector
Implements v0.0.1 of OpenBrain:

- FastAPI REST API (capture, search, recent, stats) with Bearer auth
- MCP server (streamable HTTP at /mcp) exposing all 4 tools
- pgvector schema (vector(1024) for bge-m3)
- asyncpg connection pool with lazy init + graceful close
- Ollama embedding client with fallback (stores thought without vector if Ollama unreachable)
- Woodpecker CI pipeline (lint + kaniko build + push to Gitea registry)
- Portainer/Swarm deployment compose
- Mosaic framework files: AGENTS.md, PRD.md, TASKS.md, scratchpad

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:25:07 -06:00