Content OS: content calendar, AI engine, chat assistant, MCP server - #1
Merged
Conversation
Add a new content_calendar app that mirrors the content-planning spreadsheet as a ContentItem model, with calendar/board/table views cloned from the existing Task views. - ContentItem: scheduled_date, pillar, content_type, topic, M2M to a small Platform model, hook/caption/CTA/hashtags/tags_links/audio, image_video_cover file, content_link, status + approval_status, and an optional FK to projects.Project. - Platform seeded (TikTok/Instagram/Pinterest/Facebook/YouTube/WhatsApp) via data migration so it's populated on install. - Calendar (month grid), board (grouped by approval status for review), and table views + UI create/edit/delete, all LoginRequiredMixin. - DRF ContentItem/Platform viewsets, full admin CRUD, nav links. - Tests for calendar render, board grouping, and approval updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an ai_settings app so no AI feature is locked to one provider. - AIProviderConfig: one row per provider (openai/anthropic/gemini), model_name, is_active (single active enforced on save). The API key is encrypted at rest with Fernet, keyed from SECRET_KEY (ai_settings/ encryption.py) — never stored as plaintext. - ai_client.py: one adapter with generate(system, user, temperature) and generate_with_tools(messages, tools, ...) returning a normalized ToolTurn, dispatching to OpenAI / Anthropic / Gemini via each native SDK. generate_with_tools is added now (used from Phase 4) so the interface is settled once. - Settings page (login-gated) to add keys, choose the active provider, and a "test connection" button that calls generate() and shows the reply inline. - Swap deprecated google-generativeai for the supported google-genai SDK. - Tests for encryption round-trip, single-active, key preservation, settings save, and adapter error paths. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Port ai-marketing's content engine into content_calendar, rewired to the Phase 2 provider-agnostic adapter. - VoiceProfile (single-user singleton) + distill_voice(): one AI call turns pasted writing samples into a structured, reusable voice. - PromptEnhancer: prompt layering adapted to return (system, user) for ai_client.generate() and to fold in the voice profile; ContentItem post types map onto the social prompt category. - ContentTemplate / ContentTemplatePrompt: a named recipe of ordered, per-field prompts (hook/caption/CTA/hashtags) that land in one ContentItem. - generate_content_item(): run a template or a free-text brief and create a draft ContentItem with approval_status="ready", using the active provider. - Generate panel + Voice profile pages (login-gated), toolbar "Generate" button, admin for templates/voice. Tests mock the adapter (no live calls). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a chat assistant that acts on the calendar by calling tools. - tools.py: the shared tool set (create_content_item, list_content_items, update_status, reschedule_content_item, generate_draft, distill_voice, get_calendar_month) as plain functions returning JSON-serializable dicts, plus normalized schemas and an execute_tool dispatcher. This is the single source of truth reused verbatim by the Phase 5 MCP server. (reschedule_content_item is added beyond the plan's six tools to satisfy the "move Tuesday's post to Thursday" acceptance criterion cleanly.) - agent.py: run_turn() drives ai_client.generate_with_tools() in a loop — execute tool calls, feed results back, repeat until a plain-text reply, capped at MAX_STEPS. - Chat page: session-backed transcript, vanilla fetch + Tailwind (matching the app's existing JS conventions — the codebase has no HTMX), with a thinking indicator, Enter-to-send, and clear-chat. - Tests mock the adapter and cover every tool, the loop (incl. the cap), transcript filtering, and the chat views. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expose the Phase 4 tool set to Claude Desktop / Cowork / Claude Code over MCP's stdio transport — no new business logic, a second transport. - mcp_server/server.py: FastMCP server with seven @mcp.tool() wrappers that call straight into ai_assistant.tools. Typed signatures give Claude clean input schemas. Runs standalone or imported after django.setup(). - runmcp management command launches it over stdio (stdout reserved for the protocol; status to stderr). - DJANGO_ALLOW_ASYNC_UNSAFE is set in the server: FastMCP runs sync tools on its event loop, and this single-user, one-request-at-a-time local server can safely run SQLite queries there rather than threading every ORM call. - mcp_server/README.md: connect-to-Claude doc — per-tool summary, one example prompt each, and the Desktop/Code config pointing at a local install. - Pin mcp<2 (the 1.x line providing the @server.tool()/FastMCP API the plan targets; 2.0 dropped it). Verified end-to-end via a real stdio handshake (initialize + tools/list + live tool call). Tests cover registration and the wrappers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep CLAUDE_CODE_KICKOFF_PROMPT.md and CONTENT_OS_BUILD_PLAN.md on disk as local reference but out of the repository. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the MCP connection one-click for non-technical owners: on first run the app registers itself in Claude Desktop's config, so they never hand-edit JSON. - mcp_server/desktop_connect.py: safe, never-raising merge into claude_desktop_config.json. Preserves other keys/servers, refuses to clobber an unparseable file, idempotent. Dev points at `python manage.py runmcp`; packaged points at the sibling ProjectTracker-mcp.exe. - desktop.py: first-run hook (once, via a marker file; retries only while Claude Desktop is absent) + a self-clearing "restart Claude Desktop" banner shown via a ?claude=connected URL flag. - mcp_launcher.py: console entry point for the packaged MCP exe (stdio needs real stdin/stdout, which a windowed exe lacks) — also usable in dev. - connect_claude management command for a manual/assisted turn-on. - project_tracker.spec: FIX — it was missing all four new apps (packaged build would 500); add them + their templates, swap google.generativeai for google.genai, add mcp, and build a second console ProjectTracker-mcp.exe. - Docs: Requirements (needs Claude Desktop) + free-vs-API-key sections in the MCP README and a friendly Section 8 in HOW-TO. - Tests for the config merge (create/idempotent/preserve/no-claude/unreadable/ dev+frozen entry). Verified in dev: connect_claude is idempotent and mcp_launcher speaks stdio with all 7 tools. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
collect_all("mcp") imported mcp.cli, which calls sys.exit(1) at import time
when the optional 'typer' dependency is absent, crashing the analyzer. Collect
only mcp.server/client/shared (plus mcp + mcp.types) and the package data;
the CLI isn't used. Verified: both ProjectTracker.exe and ProjectTracker-mcp.exe
build, and the packaged MCP exe completes an stdio handshake with all 7 tools.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Turns Project Tracker into a Content OS — a content calendar with a provider-agnostic AI engine, a chat assistant, and an MCP server so the calendar can be driven from Claude Desktop. Single-user, single SQLite, no multi-tenancy. Built in five phases plus a Claude Desktop auto-connect, each committed separately.
What's included
content_calendar:ContentItem(the spreadsheet columns) +Platform(M2M, seeded), calendar/board/table views, DRF, admin.ai_settings:AIProviderConfigwith Fernet-encrypted keys, oneai_clientadapter (generate+generate_with_tools) across OpenAI / Anthropic / Gemini, settings page with live "test connection".VoiceProfile+distill_voice,PromptEnhancer,ContentTemplate/ContentTemplatePrompt; a Generate panel producing draftContentItems.ai_assistant: shared tool set + agent loop, session-backed chat page.mcp_server: same tools over MCP stdio (FastMCP),runmcpcommand, connect-to-Claude doc.ProjectTracker-mcp.exe.Deliberate deviations from the plan
google-genai(plan's SDK is end-of-life);mcppinned<2; addedreschedule_content_item; chat UI uses vanilla fetch (no HTMX in codebase).Cost model
Driving the calendar via Claude Desktop runs on the user's Claude subscription (no API key). The API key is only for the in-app Generate/Assistant and
generate_draft/distill_voice.Testing
100 tests pass. Packaged two-exe build verified; frozen
ProjectTracker-mcp.execompletes an MCP stdio handshake with all 7 tools.🤖 Generated with Claude Code