SanTech Content Engine MCP Server
Enables YouTube competitor research, signal analysis, and transcript-aware pack building for content ideation and scriptwriting.
README
SanTech Content Engine
Local-first YouTube research-to-script engine for SanTech010.
The backend performs deterministic work: YouTube fetching, storage, outlier math, pack building, validation, save/select/export, and MCP tool exposure. Connected AI clients perform creative and judgment work using backend packs as source of truth.
Current status: offline backend, MCP backbone, quota guard, resource import, recent-only outliers, early velocity signals, combined signal reports, and signal-target transcript acquisition implemented.
Important MCP rule: source files sync locally on MCP HTTP startup and before YouTube collection. get_signal_research_pack reads the current local database. It does not pull fresh YouTube data. Use get_project_status to check freshness and source-sync warnings.
Verified:
python -m pytest tests -q
python -m compileall -q src
New Laptop Setup
On a fresh Windows laptop:
git clone git@github.com:budhasantosh010/san-tech-yt-research-titles-scripts.git
Set-Location -LiteralPath ".\san-tech-yt-research-titles-scripts"
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\bootstrap-windows.ps1
Then edit .env locally and add:
YOUTUBE_API_KEYSMCP_ROUTE_SECRETALLOWED_HOSTSwith your Tailscale Funnel hostname
Do not commit .env.
Before pushing from any laptop:
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-github-ready.ps1
Full reproducibility instructions live in DOCS/FUTURE_PROOF_SETUP.md.
Daily MCP Startup
Use two PowerShell terminals.
Terminal 1:
$project = "C:\Users\Lenovo\Music\Startups\YT Automations\1 San Tech Channel Research, Title & Script with Codex"
Set-Location -LiteralPath $project
.\scripts\run-mcp-http.ps1
Terminal 2:
$project = "C:\Users\Lenovo\Music\Startups\YT Automations\1 San Tech Channel Research, Title & Script with Codex"
Set-Location -LiteralPath $project
.\scripts\start-funnel.ps1
Good Funnel output should show:
proxy http://127.0.0.1:3001
ChatGPT Connector URL Format
Use this shape:
https://<machine>.<tailnet>.ts.net/mcp/YOUR_ROUTE_SECRET/
Never include brackets around route secret.
Correct:
https://desktop-fdce9ak.taila47816.ts.net/mcp/abc123.../
Wrong:
https://desktop-fdce9ak.taila47816.ts.net/mcp/<abc123...>/
Use one tool call at a time in ChatGPT. No parallel tool calls. For connection tests, call only get_project_status.
Implemented:
- SQLite schema
- config loader
- competitor storage
- video/snapshot storage
- recent-only outlier math and persistence
- early velocity signal math and persistence
- YouTube Data API adapter with fake-client tests
- viral title collection importer for CSV/XLSX
- video idea save/list/select
- title idea save/list/select
- script points save/select
- context pack builders
- transcript save/get/list-missing storage
- signal-target transcript acquisition adapters
- transcript acquisition attempt tracking
- transcript-aware outlier research packs
- script save/export
- FastMCP server wrapper
- workflow prompt templates
Still needs live/user-provided inputs:
YOUTUBE_API_KEYYOUTUBE_API_KEYSfor comma-separated multiple keys- competitor channel list
- real viral title/video collection file
- ChatGPT MCP connector/tunnel setup
Quota safety:
YOUTUBE_MAX_DAILY_QUOTA_FRACTION=0.05limits the app to 5% of each key's configured daily quota.YOUTUBE_CACHE_MAX_AGE_HOURS=24prevents refetching fresh video details/snapshots.RESEARCH_STALE_AFTER_HOURS=24controls whenget_project_statuswarns that research data is stale.AUTO_SYNC_SOURCES_ON_STARTUP=truekeeps competitor and viral sources synced locally when the MCP HTTP server starts.AUTO_SYNC_DEACTIVATE_MISSING=falsemeans startup sync repairs/reactivates source rows but does not deactivate missing competitors unless explicitly enabled.- API keys belong in
.env, which is ignored by Git.
Resource files:
- Competitors source of truth:
resources/competitors/santech_competitors.txt - Viral titles:
resources/viral titles in adjacent niches
Competitor TXT format:
- one absolute YouTube channel URL per line
- no display names
- no notes
- no commas
- no copied YouTube search/export rows
Messy CSV/XLSX/MD/TXT files can be inspected/imported, but do not use them as the canonical competitor source. If a sync source has zero files, zero rows, or zero valid YouTube channel URLs, deactivation is skipped for safety.
Signal workflow
Current deterministic workflow:
- Update
resources/competitors/santech_competitors.txtif competitor sources change. - Update viral title CSV/XLSX files if the viral title collection changes.
- Start the MCP HTTP server; backend auto-syncs sources locally.
- Refresh YouTube data and save a new snapshot row per collection run.
- Calculate recent outliers.
- Calculate early velocity.
- Dump a combined signal report.
- Fetch transcripts for selected signal targets only.
- Build transcript-aware research packs.
- Later, ChatGPT analyzes and generates ideas/titles/scripts.
MCP tool boundaries:
- Source sync is automatic on backend startup and before
collect_all_competitors. sync_competitors_from_fileandsync_viral_collectionremain admin/debug tools, but ChatGPT should not call them during normal use.scripts/sync-sources.ps1runs source sync locally without ChatGPT.scripts/run-research-refresh.ps1runs local source sync, YouTube collection, signal calculation, and project status from PowerShell.refresh_research_datacan collect YouTube stats and recalculate outlier/velocity signals. It does not fetch transcripts.get_signal_research_packis the read tool ChatGPT should use after freshness is acceptable.mark_signal_reviewedcan mark a signal asreviewed,approved,rejected,used, orsuppressed; default reports exclude reviewed/rejected/used/suppressed signals.
Recent outlier means a recent video already beat that channel's recent baseline.
Early velocity means a new video is moving unusually fast and may become an outlier.
True recent velocity requires at least two snapshots. If only one snapshot exists, the system uses lifetime velocity as a rough fallback.
Canonical competitor source sync:
python -m santech_engine.cli sync-sources
Signal commands:
python -m santech_engine.cli collect-all --limit 10
python -m santech_engine.cli calculate-outliers --recent-only --all-competitors
python -m santech_engine.cli list-outliers --limit 5
python -m santech_engine.cli dump-outlier-report --limit 20 --output exports/recent-outliers.json
python -m santech_engine.cli calculate-velocity --all-competitors
python -m santech_engine.cli list-velocity-signals --limit 10
python -m santech_engine.cli dump-velocity-report --limit 20 --output exports/early-velocity.json
python -m santech_engine.cli dump-signal-report --output exports/signal-report.json
python -m santech_engine.cli fetch-transcripts-for-signal-targets --adapter youtube_transcript_ai --limit-outliers 5 --limit-velocity 5
Transcript acquisition
This project supports transcript-aware research packs.
The system does not fetch transcripts for every competitor video.
Flow:
- Collect competitor videos.
- Calculate recent outliers and early velocity.
- Fetch transcripts only for combined signal targets.
- Cache successful transcripts.
- Mark missing/failed transcripts honestly.
- Include real transcript text in outlier packs only when available.
Default adapter:
youtube_transcript_ai
Backup adapter:
youtube_transcript_ioifYOUTUBE_TRANSCRIPT_IO_API_TOKENis set
Manual fallback:
- If automatic fetching fails for an important outlier, the user can paste transcript text into ChatGPT.
- ChatGPT can then call
save_video_transcriptthrough MCP to cache it.
Warnings:
- Transcript providers are not the official YouTube Data API.
- They may fail or change.
- Do not use aggressive scraping/proxy bypassing.
- Keep fetches low-volume and signal-first.
- The system must not infer or invent what a video said from title/metrics alone.
Useful local commands:
python -m santech_engine.cli import-competitors
python -m santech_engine.cli import-viral-collection
python -m santech_engine.cli doctor
python -m santech_engine.cli setup-env
python -m santech_engine.cli test-transcript-provider --adapter youtube_transcript_ai
python -m santech_engine.cli smoke-test
python -m santech_engine.cli collect-all --limit 5
python -m santech_engine.cli calculate-outliers --recent-only --all-competitors
python -m santech_engine.cli calculate-velocity --all-competitors
python -m santech_engine.cli dump-signal-report --output .\exports\signal-report.json
python -m santech_engine.cli fetch-transcripts-for-signal-targets --adapter youtube_transcript_ai --limit-outliers 5 --limit-velocity 5
python -m santech_engine.cli transcript-status --video-id 123
python -m santech_engine.cli list-transcript-attempts --limit 20
python -m santech_engine.cli save-transcript --video-id 123 --file .\transcript.txt
python -m santech_engine.cli dump-outlier-pack --include-transcripts --output .\exports\outlier-pack.json
python -m santech_engine.cli dump-title-pack --idea-id 1 --output .\exports\title-pack.json
python -m santech_engine.cli dump-script-pack --title-id 1 --output .\exports\script-pack.json
Run MCP server locally:
python -m santech_engine.mcp_server
ChatGPT MCP via Tailscale Funnel
Use this only after the local backend packs are truthful.
- Create local
.env:
Copy-Item .env.example .env
- Set the MCP bridge values in
.env.
MCP_HOST=127.0.0.1
MCP_PORT=3001
MCP_ROUTE_SECRET=<your-long-secret>
MCP_BEARER_TOKEN=
ALLOWED_ORIGINS=https://chatgpt.com,https://chat.openai.com
ALLOWED_HOSTS=127.0.0.1,localhost,<your-machine>.<your-tailnet>.ts.net
FUNNEL_BASE_URL=
Rules:
- At least 32 characters.
- Do not commit
.env. - Do not paste the secret into docs.
- Keep
MCP_BEARER_TOKENblank if the ChatGPT connector usesAuthentication: No Auth. - Add your real Tailscale Funnel hostname to
ALLOWED_HOSTS.
- Run the HTTP bridge doctor:
.\scripts\doctor-mcp-http.ps1
- Start the local MCP HTTP server:
.\scripts\run-mcp-http.ps1
- In another terminal, start Tailscale Funnel:
.\scripts\start-funnel.ps1
- Add this URL as the ChatGPT custom connector URL:
https://<machine>.<tailnet>.ts.net/mcp/<MCP_ROUTE_SECRET>
Use your real Tailscale Funnel hostname and your local route secret value.
- In ChatGPT, test:
get_project_status
- Then test the main research pack:
get_signal_research_pack
Expected route:
ChatGPT custom connector
-> Tailscale Funnel HTTPS URL
-> http://127.0.0.1:3001/mcp/<MCP_ROUTE_SECRET>
-> SanTech MCP tools
-> SQLite / YouTube API / transcript providers
Security notes:
- The Python server binds only to
127.0.0.1. - The default SanTech MCP HTTP port is
3001. - The MCP route is mounted under
/mcp/<MCP_ROUTE_SECRET>. - Allowed origins default to
https://chatgpt.comandhttps://chat.openai.com. - Allowed hosts default to
127.0.0.1andlocalhost; add the Tailscale Funnel hostname throughALLOWED_HOSTSorFUNNEL_BASE_URL. - If another MCP bridge, such as the X/Spectre bridge, is using the same Tailscale Funnel root hostname, run only one of them through that public root at a time unless you add a gateway/router.
- Scripts and doctor checks do not print API keys, bearer tokens, or the MCP route secret.
- Stop Funnel with:
.\scripts\stop-funnel.ps1
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.