SideShift Scanner
Whip UGC Program Automation
The automation layer on top of SideShift for running Whip's UGC creator partnership program. Video performance data already lives in SideShift — this system organizes what SideShift (and Matthew's own judgment) surfaces, turns it into action, and keeps him from manually rebuilding a tracker every week.
Full spec: ugc-program-automation-spec.md. Design principle: Matthew never structures data by hand, and the system never contacts a creator on its own — it drafts, he sends.
flowchart LR
SS["SideShift API"] -- sync --> DB[("Local SQLite store")]
DB -- triage --> DB
DB -- compile --> DG["Weekly Digest"]
DB -- plan --> CAL["Google Calendar\n(via Calendar.app)"]
DG -- Gmail draft --> M["Matthew reviews & sends"]
AGENT["Claude Code / jcode"] -- MCP tools --> DB
M -- voice/typed notes --> AGENTThe core loop (spec section 3)
Ingest —
sync_datapulls a SideShift export into the Content Log, orrecord_manual_contentfiles raw numbers Matthew provides in chat.Triage —
run_triageflags each post Top/Normal/Underperforming relative to that creator's own recent baseline (not a fixed threshold).Surface —
compile_digest/render_digestreturn what's worth watching and why.Capture — Matthew watches, then tells the system his read in plain language;
capture_watch_notesresolves it safely, orfind_content+record_watch_notesfile it against the right content_id.Synthesize —
synthesize_feedback_draftcombines the data pattern with Matthew's notes into a starting draft. Drafted only.Calendar —
sync_calendarkeeps a dedicated Google Calendar current: payment dates, contract renewals, follow-up nudges.Digest —
run_weekly_routineruns the whole automated chain on a schedule;compile_digestanswers on-demand queries any time.
Human-in-the-loop rule (spec section 5, non-negotiable)
Fully automated: parsing/filing data, flagging performance, synthesizing patterns, drafting feedback text, creating/updating calendar events, compiling the digest.
Requires Matthew's action: anything that reaches a creator. There is no
send_feedback tool anywhere in this codebase — save_feedback_draft only
ever writes a Draft row to the Feedback Log. Getting a draft in front of
Matthew is the calling agent's job (stage it as a Gmail draft with its own
gmail tool), and sending it is Matthew's.
Calendar events are the one thing this system creates/updates without
approval (low-risk, easily corrected) — but sync_calendar only ever
touches events it created itself. Every system-created event is tagged with
a stable marker; a Matthew-made event on the same calendar is never edited
or deleted, even if it collides on date or title. See
calendar_sync.py.
Setup
1. Install
git clone <this-repo>
cd sideshift-scanner
python3 -m venv .venv && source .venv/bin/activate && pip install -e ".[dev]"2. SideShift API key — copy the template and paste in your key (SideShift dashboard → Settings → Integrations):
cp .env.example .env3. Point the agent at your Python — copy the template and fill in the
absolute path to .venv/bin/python from step 1:
cp .mcp.json.example .mcp.json4. Add the dedicated calendar to Calendar.app (spec section 8 Q3).
Calendar sync works by driving macOS Calendar.app via JXA rather than the
Google Calendar REST API — no OAuth app, no consent screen, no per-machine
token refresh (see calendar_sync.py
docstring for the full rationale). Create (or pick) a dedicated Google
Calendar for the program, subscribe it in Calendar.app → Settings →
Accounts (it should already be there if it's under the same Google
account as Calendar.app), and note its exact display name. Default is
"whip"; override with calendar_name on any calendar tool/command.
5. Restart Claude Code / jcode in this folder to pick up the MCP server.
That's it — everything else is a chat message or a CLI command.
Just ask (via the agent)
Sync my latest SideShift data and run triage
What should I watch this week?
Ava just posted a TikTok that felt flat, the hook was too slow -- file that
Draft feedback for Marcus based on his last three underperforming posts
Update the calendar with upcoming payments and follow-ups
Give me this week's digestThe agent resolves freeform descriptions to the right creator/content_id
via find_content, files notes, drafts feedback, and stages Gmail drafts
using its own gmail tool — this MCP server never touches Gmail itself.
MCP tools
Tool | Spec step | Purpose |
| 1. Ingest | Pull SideShift data ( |
| 1. Ingest | File raw views + engagement when Matthew states the numbers directly |
| 2. Triage | Recompute Top/Normal/Underperforming per creator baseline |
| 2/3 | Content Log rows, filterable by creator/platform/flag/watched |
| 3/7 | Structured weekly-digest data on demand: per-creator status/trends, top performers with real metrics, trending formats, watchlist |
| 3/7 | Same, as email-ready markdown |
| 4. Capture | Resolve freeform description → candidate content_ids |
| 4. Capture | File Matthew's freeform read against a content_id |
| 4. Capture | Resolve a freeform post reference and file notes only when unambiguous |
| 5. Synthesize | Persist drafted feedback as |
| 5. Synthesize | Create a data- and note-informed feedback |
| 5 | List the Feedback Log |
| roster | Creator Roster CRUD |
| 6. Calendar | Reconcile the dedicated calendar against the roster |
| 6 | Same, without touching Calendar.app |
| 7. Digest | sync → triage → calendar sync → digest, one call |
CLI
Every tool above also has a ugc-cli command (sync, record-content, triage, digest,
creators, content, find-content, watch-notes, draft-feedback,
capture-notes, synthesize-feedback, feedback-drafts, update-creator, calendar-plan, calendar-sync,
weekly-routine):
ugc-cli weekly-routine --today 2026-08-25
ugc-cli digest --format text
ugc-cli calendar-sync --dry-runWeekly automation (spec section 6)
run_weekly_routine / ugc-cli weekly-routine runs sync → triage →
calendar sync → digest compilation in one call and returns
digest_markdown. It never touches Gmail — the scheduled agent wakeup that
drives it (see jcode's ScheduleWakeup, configured separately per
machine) stages that markdown as a Gmail draft addressed to Matthew each
Monday morning, which he reviews and sends like any other draft. On-demand
digests work the same way any time via compile_digest / ugc-cli digest.
Live dashboard
A read-only static dashboard mirrors compile_digest's output (creator
status/trends, top performers with real metrics, trending formats, watch
list, upcoming dates) at https://whip-ugc-digest.vercel.app, refreshed
daily via scripts/refresh_dashboard.sh (sync → triage → export JSON →
vercel deploy) and a separate daily ScheduleWakeup. Source lives in
web/ (single static index.html + public/data.json, no build step,
no framework) and scripts/export_digest.py (thin JSON serializer around
compile_digest, no new computation).
The URL has no authentication — anyone with the link can see creator names, handles, and performance numbers. Fine for a personal quick-glance tool; add Vercel password protection (Project Settings → Deployment Protection) before sharing the link with anyone outside your own use.
To refresh manually: ./scripts/refresh_dashboard.sh (requires the Vercel
CLI logged in via vercel login, run once per machine).
Data model (spec section 4)
Three logical tables backed by SQLite (data/ugc_analytics.db, gitignored
locally but expected to be shared via whatever sync mechanism the deploy
environment uses):
Creator Roster (
creators) — one row per creator: platforms, status, contact, contract/payment/follow-up dates, notes.Content Log (
content_items+performance_metrics+content_annotations) — one logical row per post: SideShift-sourced fields never touch Matthew/system-managed fields (watched,matthew_notes,system_synthesis,performance_flag) on resync.Feedback Log (
feedback_log) — one row per drafted feedback instance:Draftuntil Matthew sends it himself.
Triage formula (spec section 8 Q5 — first pass, not finalized)
performance_flag is a tie-aware percentile of a post's engagement rate
against that same creator's trailing 5 posts on the same platform
(never mixing e.g. YouTube Shorts' high-view/low-engagement pattern into a
TikTok baseline). Top ≥ 70th percentile, Underperforming ≤ 30th, and a
cohort under 3 prior posts is honestly reported as insufficient_data
rather than guessed. See triage.py for the
exact thresholds — these need Matthew's sign-off against real synced data
per the spec.
Tests
pytest -q96 tests cover schema/upsert semantics, triage math (including the
platform-scoping and small-cohort-honesty guarantees), CSV + mocked-API
ingestion, digest compilation and rendering, calendar plan computation +
mocked JXA reconciliation, the weekly routine orchestration, every MCP
tool via mcp.call_tool, and the CLI via Typer's CliRunner. The JXA
calendar script itself (create/update/delete, idempotency, and never
touching a non-marker event) was additionally validated by hand against a
live Google Calendar through Calendar.app — see calendar_sync.py's
module docstring.
Non-goals (v1, spec section 2)
No new video-performance analytics/dashboard (SideShift already covers this), no AI video-watching pipeline (spec section 7, Phase 2), not a CRM/payment processor (tracks dates and status, doesn't execute payments).
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/matthewhuang11/sideshift-scanner'
If you have feedback or need assistance with the MCP directory API, please join our Discord server