SanTech Content Engine MCP Server
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 srcNew 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.ps1Then 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.ps1Full 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.ps1Terminal 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.ps1Good Funnel output should show:
proxy http://127.0.0.1:3001ChatGPT 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 keyscompetitor 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.txtViral 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-sourcesSignal 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 5Transcript 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.jsonRun MCP server locally:
python -m santech_engine.mcp_serverChatGPT MCP via Tailscale Funnel
Use this only after the local backend packs are truthful.
Create local
.env:
Copy-Item .env.example .envSet 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.ps1Start the local MCP HTTP server:
.\scripts\run-mcp-http.ps1In another terminal, start Tailscale Funnel:
.\scripts\start-funnel.ps1Add 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_statusThen test the main research pack:
get_signal_research_packExpected 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 providersSecurity 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.ps1Latest 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/budhasantosh010/san-tech-yt-research-titles-scripts'
If you have feedback or need assistance with the MCP directory API, please join our Discord server