Skip to content
Closed

Mcp3 #210

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Chronicle
# Chronicle (fork from https://github.com/chronicler-ai/chronicle)

Self-hostable AI system that captures audio/video data from OMI devices and other sources to generate memories, action items, and contextual insights about your conversations and daily interactions.

Expand Down
5 changes: 5 additions & 0 deletions backends/advanced/src/advanced_omi_backend/app_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from advanced_omi_backend.routers.modules.websocket_routes import router as websocket_router
from advanced_omi_backend.services.audio_service import get_audio_stream_service
from advanced_omi_backend.task_manager import init_task_manager, get_task_manager
from advanced_omi_backend.services.mcp_server import setup_mcp_server

logger = logging.getLogger(__name__)
application_logger = logging.getLogger("audio_processing")
Expand Down Expand Up @@ -205,6 +206,10 @@ def create_app() -> FastAPI:
tags=["users"],
)

# Setup MCP server for conversation access
setup_mcp_server(app)
logger.info("MCP server configured for conversation access")

# Mount static files LAST (mounts are catch-all patterns)
CHUNK_DIR = Path("/app/audio_chunks")
app.mount("/audio", StaticFiles(directory=CHUNK_DIR), name="audio")
Expand Down
5 changes: 5 additions & 0 deletions backends/advanced/src/advanced_omi_backend/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class UserRead(BaseUser[PydanticObjectId]):
display_name: Optional[str] = None
registered_clients: dict[str, dict] = Field(default_factory=dict)
primary_speakers: list[dict] = Field(default_factory=list)
api_key: Optional[str] = None
api_key_created_at: Optional[datetime] = None


class UserUpdate(BaseUserUpdate):
Expand Down Expand Up @@ -62,6 +64,9 @@ class User(BeanieBaseUser, Document):
registered_clients: dict[str, dict] = Field(default_factory=dict)
# Speaker processing filter configuration
primary_speakers: list[dict] = Field(default_factory=list)
# API key for MCP access
api_key: Optional[str] = None
api_key_created_at: Optional[datetime] = None

class Settings:
name = "users" # Collection name in MongoDB - standardized from "fastapi_users"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
"""

import logging
import secrets
from datetime import UTC, datetime

from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, HTTPException

from advanced_omi_backend.auth import current_superuser
from advanced_omi_backend.auth import current_active_user, current_superuser
from advanced_omi_backend.controllers import user_controller
from advanced_omi_backend.users import User, UserCreate, UserUpdate

Expand Down Expand Up @@ -44,3 +46,42 @@ async def delete_user(
):
"""Delete a user and optionally their associated data. Admin only."""
return await user_controller.delete_user(user_id, delete_conversations, delete_memories)


@router.post("/me/api-key")
async def generate_api_key(current_user: User = Depends(current_active_user)):
"""Generate a new API key for the current user."""
try:
# Generate a secure random API key (32 bytes = 64 hex characters)
new_api_key = secrets.token_urlsafe(32)

# Update user with new API key
current_user.api_key = new_api_key
current_user.api_key_created_at = datetime.now(UTC)
await current_user.save()

logger.info(f"Generated new API key for user {current_user.id}")

return {
"api_key": new_api_key,
"created_at": current_user.api_key_created_at.isoformat()
}
except Exception as e:
logger.error(f"Failed to generate API key for user {current_user.id}: {e}")
raise HTTPException(status_code=500, detail="Failed to generate API key")


@router.delete("/me/api-key")
async def revoke_api_key(current_user: User = Depends(current_active_user)):
"""Revoke the current user's API key."""
try:
current_user.api_key = None
current_user.api_key_created_at = None
await current_user.save()

logger.info(f"Revoked API key for user {current_user.id}")

return {"status": "success", "message": "API key revoked"}
except Exception as e:
logger.error(f"Failed to revoke API key for user {current_user.id}: {e}")
raise HTTPException(status_code=500, detail="Failed to revoke API key")
Loading
Loading