bigwolfe
init
31b3b17

Phase 0: Research & Technical Decisions

1. FastMCP Metadata Injection

Decision: Return CallToolResult with _meta for UI tools.

Strategy:

  • We will stop returning pure Pydantic models from tools that need to trigger widgets (read_note, search_notes).
  • Instead, these tools will instantiate the Pydantic model, dump it to a dictionary, and wrap it in a CallToolResult object.
  • The _meta field will contain openai: { outputTemplate: "..." }.
  • Non-UI tools (e.g., list_notes, delete_note) will continue to return Pydantic models or simple text to keep them lightweight.

Rationale: This aligns with the OpenAI Apps SDK pattern and allows us to trigger widgets without breaking the existing schema validation (since structuredContent will still match the Pydantic schema).

2. React Widget Strategy

Decision: Use a separate Vite entry point (widget.html + widget.tsx).

Strategy:

  • Create frontend/widget.html as a lightweight entry point.
  • Create frontend/src/widget.tsx to render the widget application.
  • Refactor NoteViewer.tsx into a "pure" component (if it isn't already) that can be imported by both App.tsx and widget.tsx.
  • Use vite-plugin-html or manual rollup config to output multiple HTML files.

Rationale:

  • Isolation: Prevents the main app's router, sidebar, and heavy layout styles from leaking into the iframe.
  • Performance: The widget bundle will be smaller.
  • Simplicity: Easier to reason about "widget state" when it's a fresh React mount rather than a route transition in a complex SPA.

3. Authentication

Decision: Use a configurable "Service Token" strategy.

Strategy:

  • Refactor AuthService to support a TokenValidator interface or strategy.
  • Implement JWTValidator (existing) and StaticTokenValidator (new).
  • Add CHATGPT_SERVICE_TOKEN to AppConfig.
  • If CHATGPT_SERVICE_TOKEN is set, the backend will accept it as a valid Bearer token for any user context (or a specific "chatgpt-bot" user).

Rationale:

  • Hugging Face OAuth is not compatible with the Apps SDK OIDC flow.
  • Implementing a full OIDC provider is out of scope for the hackathon.
  • A static service token is secure enough for a demo/hackathon submission and easy to configure in the OpenAI Developer Platform.

4. Infrastructure & Hosting

Decision: Serve widget.html via FastAPI static mount with Skybridge MIME type.

Strategy:

  • Update backend/src/api/main.py to serve frontend/dist/widget.html on a specific route (e.g., /widget).
  • Ensure the Content-Type header is text/html+skybridge (or whatever the specific requirement is, usually just serving it is enough, but we will double-check if OpenAI needs specific headers). Correction: The expert mentioned text/html+skybridge media type for FileResponse.
  • Update CORS to allow https://chatgpt.com (and https://*.chatgpt.com).

Rationale: Required for the widget to load inside the ChatGPT iframe.