feat(mcp): scaffold in-app FastMCP package

Empty FastMCP instance with the post-pivot instructions block. Tools
get registered in phases 2 and 3; ASGI mounting + bearer-auth comes
in task 1.4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 19:12:57 -04:00
parent b97a8ce457
commit 198f11ee09
2 changed files with 46 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
"""In-app MCP server. Exposes Fabled Scribe data via the MCP streamable-HTTP transport.
Auth uses the existing `api_keys` table: a Bearer token in the Authorization
header resolves to a user, and every tool call acts on that user's data only.
"""
from fabledassistant.mcp.server import build_mcp_server, mount_mcp
__all__ = ["build_mcp_server", "mount_mcp"]
+38
View File
@@ -0,0 +1,38 @@
"""FastMCP instance + Quart mount-point. Tools are registered in mcp/tools/."""
from __future__ import annotations
from mcp.server.fastmcp import FastMCP
from quart import Quart
_INSTRUCTIONS = """
Fabled Scribe is the user's self-hosted second-brain and project-management
data store. You (Claude) are the assistant.
Hierarchy: Project -> Milestone -> Task/Note.
- Notes and Tasks share a model; tasks are notes with is_task=True.
- Use fable_*_note tools for notes, fable_*_task tools for tasks.
- Typed entities (person, place, list) are notes with a type field plus
type-specific columns; use the dedicated tools for those.
- Tags are plain strings (no `#` prefix). Empty list clears tags; omit to leave
unchanged on updates.
- For optional integer FKs (project_id, milestone_id, parent_id), use 0 to mean
"not set".
"""
def build_mcp_server() -> FastMCP:
"""Build the FastMCP instance with all tools registered."""
mcp = FastMCP("fable", instructions=_INSTRUCTIONS.strip())
# Tools will be registered here in Phase 2/3.
return mcp
def mount_mcp(app: Quart) -> None:
"""Mount the FastMCP streamable-HTTP ASGI sub-app at /mcp on the Quart app.
Phase 1.2 scaffold: just builds and exposes the instance for tests. The
actual ASGI wiring with bearer-auth happens in Task 1.4.
"""
mcp = build_mcp_server()
app.mcp_instance = mcp