campaign-preflight-mcp
캠페인 프리플라이트
Campaign Preflight는 아웃바운드 캠페인을 위한 읽기 전용 린터입니다. 발송 전에 구성, 연락처 데이터, 개인화, 억제, 일정, 발신자 문제를 잡아냅니다.
하는 일
모든 아웃바운드 팀은 실수가 담긴 캠페인을 한 번쯤 발송해 본 적이 있습니다. 구독을 취소한 사람이 메일을 받았고, 시퀀스가 잠재 고객이 답장한 후에도 계속 후속 메일을 보냈고, 병합 필드가 병합되지 않아 200명이 "Hi {{first_name}}"을 받았습니다.
발송이 끝난 후에야 알게 됩니다.
Campaign Preflight는 캠페인의 구성, 리드, 카피, 일정, 발신자, 억제 노출에 대해 76개의 결정적 검사를 실행하고, 모든 발견 사항에 대한 근거와 함께 발송 준비 상태 판정을 반환합니다. 공급자에 쓰기 작업을 하지 않으며 어떤 것도 활성화할 수 없습니다.
하지 않는 일을 뒤에 묻어 두지 않고 앞에 명시합니다:
전달 가능성을 보장하지 않습니다. 받은 편지함 배치가 아니라 구성과 데이터를 검사하며, 전달 가능성 점수를 임의로 만들어 내지 않습니다.
법률 자문을 제공하지 않습니다. 지역, 도메인, 옵트아웃 검사는 캠페인을 사용자가 직접 구성한 정책과 비교합니다 — GDPR, CAN-SPAM, CASL이 아닙니다.
사서함을 검증하지 않습니다. 주소 검사는 구문 검사일 뿐입니다. DNS도 SMTP도 없습니다.
공급자의 안전장치를 대체하지 않습니다. 그대로 켜 두세요.
결과는 특정 시점의 스냅샷입니다. 09:00에 통과한 캠페인은 09:05에 수정될 수 있습니다.
자세한 내용은 docs/limitations.md를 참조하세요.
Related MCP server: Newsletter Tools
"확인했는데 괜찮아" ≠ "확인할 수 없었어"
이 둘을 구분하지 못하는 검사기는 검사기가 없는 것보다 나쁩니다. 권한 오류를 초록불로 바꿔 버리기 때문입니다.
Campaign Preflight는 이 구분을 구조적으로 만듭니다. 모든 공급자 읽기는 데이터 와 데이터가 존재하거나 존재하지 않는 이유를 반환하며, 모든 규칙은 필요한 데이터를 선언합니다. 해당 데이터를 사용할 수 없으면 엔진은 규칙이 실행되기 전에 UNKNOWN으로 단락시킵니다. 규칙은 이를 거부할 수 없습니다.
상황 | 결과 |
억제 목록을 읽었고, 일치하는 항목 없음 |
|
억제 목록이 제공되지 않음 |
|
억제 엔드포인트가 403 반환 |
|
캠페인의 리드가 0개 |
|
리드 엔드포인트에 연결 불가 |
|
판정은 두 가지가 아니라 네 가지입니다: READY, READY_WITH_WARNINGS, NOT_READY, INCOMPLETE.
요구 사항
Python 3.9 이상. 이것이 전부입니다.
이 패키지는 런타임 의존성이 없습니다 — 표준 라이브러리 외에는 아무것도 import하지 않습니다. httpx는 라이브 Instantly 공급자에만 필요한 선택적 추가 기능으로, 지연 import 뒤에 있습니다.
3.9 하한선은 의도적이며, 예상보다 의도적으로 낮게 잡았습니다. 플러그인이 사용자 머신에서 만날 수 있는 가장 오래된 인터프리터이며, 의존성이 없으므로 더 높일 이유가 없습니다. CI는 Linux, macOS, Windows에서 3.9부터 3.13까지, 그리고 아무것도 설치하지 않는 순수 인터프리터 작업을 실행합니다.
이 조합 덕분에 플러그인은 설치 단계 없이 실행됩니다. 이미 있는 python3을 사용합니다.
설치
Claude 플러그인으로 (마켓플레이스)
/plugin marketplace add katekruger/campaignpreflightplugin
/plugin install campaign-preflight이 저장소는 자체 마켓플레이스입니다. .claude-plugin/marketplace.json이 플러그인 매니페스트와 함께 루트에 있습니다.
Claude 플러그인으로 (로컬 체크아웃)
git clone https://github.com/katekruger/campaignpreflightplugin/plugin marketplace add ./campaignpreflightplugin
/plugin install campaign-preflightCLI로
pipx install campaign-preflight또는 체크아웃에서 바로, 아무것도 설치하지 않고:
PYTHONPATH=src python3 -m campaign_preflight.cli demoMCP 서버로
claude mcp add campaign-preflight -- campaign-preflight-mcp읽기 전용 도구 6개. 활성화, 편집, 가져오기, 발송을 할 수 있는 것은 없습니다. Claude Code 및 Claude Desktop 설정: docs/mcp.md.
빠른 시작
campaign-preflight demoAPI 키 없음. 네트워크 없음. 구성 없음.
CAMPAIGN PREFLIGHT
Campaign: Enterprise Q3 Outbound
Provider: demo
Readiness: NOT READY
Score: 0/100
Confidence: MEDIUM
BLOCKERS
[campaign.stop_on_reply]
Stop-on-reply is disabled: repliers will keep receiving follow-ups.
Remediation: Enable stop-on-reply on the campaign.
[personalization.prompt_injection]
1 contact(s) have prompt-injection text in their personalization.
Affected: s***********a@caldera.example.com
Remediation: Remove the affected personalization and review the enrichment source it came from.
[suppression.contact_listed]
1 contact(s) appear on the active suppression list.
Affected: m**********s@stonebridge.example.com
Remediation: Remove these contacts from the campaign before activation.
WARNINGS
[contacts.missing_first_name]
2 of 20 contacts (10.0%) are missing a first name.
Affected: i**o@summitforge.example.com, r******s@clearwater.example.com
Remediation: Backfill the missing first names, or use a fallback in your copy.
UNKNOWN
[senders.aggregate_capacity]
Sender capacity is unavailable: 1 of 3 senders report no daily limit.
Affected: r***n@example.com
------------------------------------------------------------------------------
Summary:
8 blockers, 17 failures, 21 warnings, 1 unknown, 32 passed
20 leads and 3 sender(s) checked in 0.0s
Confidence is MEDIUM: 1 check(s) could not run.
Point-in-time snapshot. Campaign state may change after this check ran.마지막 발견 사항에 주목하세요. 한 발신자가 일일 한도를 보고하지 않아 총 용량을 합산할 수 없습니다. 대부분의 도구는 한도를 보고하는 발신자만 합산해 숫자라고 부르겠지만, 이 도구는 모른다고 말하며 그 때문에 신뢰도를 HIGH에서 MEDIUM으로 낮춥니다.
그 구분이 바로 이 도구의 핵심 아이디어입니다.
자신의 캠페인 확인하기
플러그인이 설치되면 일상 언어로 설명하세요:
보내기 전에 이 캠페인을 확인해 줘.
내 리드 목록이야 — 문제 있는 게 있니? (붙여넣기 또는 업로드)
200명에게 3통짜리 이메일 시퀀스를 보내려고 해, 하루 80통, 평일 오전 9시~오후 5시 동부 시간. 괜찮을까?
들어가는 방법은 세 가지이며, 어떤 것도 계정이 필요 없습니다:
가지고 있는 것 | 일어나는 일 |
파일 (업로드 또는 디스크에 있음) | 직접 검사합니다. |
붙여넣은 목록 또는 일부 카피 | 임시 파일에 기록하고, 검사한 후 정리합니다. |
설명만 있음 | 캠페인 파일을 말한 내용으로 만들고, 보여준 후 검사합니다. |
모르는 것은 추측하지 않고 비워 둡니다 — 빈 필드는 "확인할 수 없음"으로 돌아오며, 그것이 정직한 답변입니다.
파일에서, 명령줄에서
campaign-preflight check \
--campaign examples/clean_campaign/campaign.yaml \
--leads examples/clean_campaign/leads.csv \
--suppressions examples/clean_campaign/suppressions.csv판정별로 하나씩, 세 가지 실제 예제가 저장소에 포함되어 있습니다:
예제 | 판정 | 종료 코드 |
|
| |
|
| |
|
|
CI에서
campaign-preflight check --campaign campaign.yaml --leads leads.csv --fail-on blocker종료 코드가 판정을 전달하므로 파이프라인에 바로 넣을 수 있습니다. docs/ci.md를 참조하세요.
내부 구성
저장소 루트 가 플러그인입니다. 트리의 두 번째 복사본은 없습니다.
.claude-plugin/ plugin manifest and marketplace manifest
skills/ the three skills, one directory each
bin/ launchers the MCP server and CLI run through
src/ the Python package: rules, engine, providers, reporters
tests/ unit, integration, contract
docs/ rules catalogue, configuration, MCP, CI, limitations, architecture
examples/ three worked campaigns, one per verdict
scripts/ generators and the plugin packager스킬
스킬 | 용도 |
| 직접 제공한 실제 캠페인 검사 — 파일, 붙여넣기, 또는 설명. |
| 번들된 샘플 데이터로 검사기가 실행되는 모습 보기. |
| 어떤 규칙이 있는지, 각 규칙이 무엇을 테스트하는지, 재조정 또는 비활성화 방법. |
경계는 의도적입니다. 각 설명은 자신의 상황을 명시하고 이웃을 가리키므로, 근접 실패도 복구 가능한 곳에 도달합니다.
검사 항목
일곱 범주에 걸친 76개 규칙. 전체 카탈로그: docs/rules.md.
범주 | 규칙 수 | 예시 |
캠페인 | 10 | 답장 시 중지 비활성화, 일일 볼륨이 임계값 초과, 발송 시간대 없음, 발송 가능일이 남지 않는 날짜 |
연락처 | 15 | 잘못된 형식의 주소, 중복(정확 및 대소문자 무시), 역할 사서함, 자리표시자 값, 제어 및 양방향 문자, 스프레드시트 수식 주입 |
억제 | 8 | 억제 목록에 있는 연락처 및 도메인, 기존 고객, 내부 주소, 경쟁사, 제한 지역 — 그리고 억제 검사가 실행될 수 있었는지 여부 |
개인화 | 13 | 렌더링되지 않은 병합 토큰, 잘못된 사람에게 보내는 인사말, 그들의 회사가 아닌 회사, 자신의 증거로 뒷받침되지 않는 주장, 오래된 리서치, 대상 페이지에서 긁어온 프롬프트 주입 텍스트 |
카피 | 13 | 첫 단계의 빈 제목, 깨진 링크, |
일정 | 9 | 잘못된 시간대, 주말 발송, 활성 일수 0, 시작 전에 끝나는 시간대, 캠페인 기간 내 DST 전환 |
발신자 | 8 | 건강 임계값 미만의 사서함, 오류 상태, 용량을 초과하는 볼륨 — 그리고 공급자가 말해 주지 않을 때의 정직한 |
이 중 어떤 것이든 도구에 물어보세요:
campaign-preflight rules list --category suppression
campaign-preflight rules explain senders.aggregate_capacity의도적으로 검사하지 않는 것
스팸 단어 규칙은 없습니다. "무료"와 "지금 행동하세요"는 어떤 증거도 아니며, 그런 목록을 넣으면 도구를 무시하도록 훈련하게 됩니다. 판단이 필요한 규칙 — 카피 길이, 링크 수, 생성 산출물 — 은 heuristic으로 표시되고 모든 보고서에 그렇게 라벨이 붙으며, 기본적으로 차단 항목이 되지 않습니다.
구성
Campaign Preflight는 합리적인 기본값과 구성 파일 없이 실행됩니다. 임계값이 다르거나, 자체 도메인 및 지역 목록에 의존하는 검사를 켜야 할 때 구성 파일을 추가하세요.
version: 1
settings:
target_timezone: America/New_York
required_variables: [first_name, company_name]
internal_domains: [ourcompany.example.com]
customer_domains: [bigcustomer.example.com]
allow_weekend_sending: false
rules:
campaign.daily_volume:
warning_above: 100
blocker_above: 250
senders.health_below_threshold:
minimum_score: 80
contacts.missing_job_title:
enabled: falsecampaign-preflight validate-config preflight.yaml
campaign-preflight check --campaign c.yaml --leads l.csv --config preflight.yaml검증은 의도적으로 엄격합니다. 알 수 없는 규칙 ID나 알 수 없는 옵션은 경고가 아니라 하드 오류입니다. 안전 검사를 조용히 비활성화하는 오타는 구성이 없는 것보다 나쁩니다.
전체 참조: docs/configuration.md.
읽기 전용이 중요한 이유
Campaign Preflight에는 쓰기를 수행하는 코드 경로가 없습니다. "우리가 선택하지 않았다"가 아니라 — 호출할 것이 아예 없습니다.
Instantly 공급자는 모든 요청을 명시적 허용 목록에 대해
(method, path)를 검사하는 전송 계층으로 라우팅하며, 요청이 프로세스를 떠나기 전에 예외를 발생시킵니다. 검사는 클라이언트 아래, 공급자 아래에 있으므로, 나중에PATCH를 추가하는 코드 변경은 캠페인을 조용히 편집하는 대신 크게 실패합니다.import 시점에 두 개의 가드가 실행됩니다: 허용 목록에
PUT,PATCH,DELETE,HEAD,OPTIONS가 포함될 수 없고,POST는 정확히 하나의 경로(/leads/list— 필터링된 읽기에 대한 Instantly의 문서화된 형식)에만 허용됩니다.MCP 서버는 등록된 도구의 이름에 변경 동사가 있거나 읽기 전용을 선언하지 않으면 시작을 거부합니다.
tests/contract/test_instantly_transport.py는 전체 method × path 행렬과 모든 문서화된 변경 엔드포인트를 테스트합니다. 거기서의 실패는 테스트 실패가 아니라 보안 사고입니다.
이것이 에이전트에게 라이브 캠페인을 맡겨도 안전한 이유입니다. 분석은 얻고 권한은 전혀 얻지 못합니다.
절대 하지 않을 일
캠페인 활성화, 일시중지, 재개 또는 예약
리드 생성, 업데이트, 이동, 병합 또는 삭제
억제 목록에 추가 또는 제거
이메일 보내기, 답장 또는 전달
전송 플랫폼의 모든 항목 수정
이러한 작업으로 가는 코드 경로는 존재하지 않으며, 두 개의 독립적인 가드(전송 허용 목록과 MCP 시작 시 검증)는 하나라도 추가되면 안전하게 차단(fail closed)됩니다.
종료 코드
코드 | 의미 |
|
|
|
|
|
|
|
|
| 구성 또는 입력 오류 |
| 공급자 또는 인증 오류 |
| 예기치 않은 내부 오류 |
--fail-on none|warning|high|blocker는 판정이 0이 아닌 종료 코드가 되는 기준을 높입니다. 판정 자체는 절대 변경하지 않습니다. INCOMPLETE는 심각도 임계값으로 무시되지 않습니다. 검사를 실행할 수 없는 것은 낮은 심각도의 발견 사항과는 다른 문제입니다.
점수 산정은 공개되며 숨겨지지 않습니다
score = 100 - sum(weight[status][severity] for every FAIL and WARN)
readiness:
NOT_READY any BLOCKER FAIL, or any HIGH FAIL
INCOMPLETE else if any critical rule is UNKNOWN
READY_WITH_WARNINGS else if any FAIL or WARN
READY otherwise그로부터 네 가지가 따라오며, 각각 테스트가 있습니다:
차단(blocker)은 항상
NOT_READY를 생성합니다. 점수가 이를 덮어쓸 수 없습니다.UNKNOWN은 아무것도 차감하지 않습니다. 공급자 장애가 나쁜 캠페인처럼 보여서는 안 됩니다. 대신 신뢰도를 낮춥니다.NOT_APPLICABLE은 아무것도 영향을 주지 않습니다.모든 차감 항목은 개별 명시됩니다.
--verbose는 직접 확인할 수 있도록 계산 과정을 출력합니다.
가중치와 중요 규칙 목록은 구성 가능합니다: docs/configuration.md.
아키텍처
flowchart LR
CLI[CLI] --> Engine
MCP[MCP server] --> Engine
Engine -->|gather| Provider{Provider}
Provider --> CSV[CSV / files]
Provider --> Instantly[Instantly v2]
Instantly --> Guard[ReadOnlyTransport]
Guard -->|allowlist| API[(Instantly API)]
Provider -->|data + why| Context[Frozen context]
Context --> Rules[76 rules]
Rules --> Score[Scoring]
Score --> Out[Terminal / JSON / Markdown]
style Guard fill:#4a1f1f,stroke:#c04040,color:#fff컨텍스트는 고정(frozen) Pydantic 모델이므로 "규칙은 입력을 절대 변경하지 않는다"는 검토가 아닌 타입 시스템에 의해 강제됩니다. 공급자별 동작은 전적으로 공급자 인터페이스 뒤에 있습니다.
전체 설계 및 위협 모델: docs/architecture.md.
개인정보 보호
기본적으로 수정(redact)됩니다. 사서함 로컬 부분은 마스킹됩니다 (
m**********s@stonebridge.example.com). 도메인은 유지됩니다. 도메인이 있어야 억제 발견 사항이 실행 가능하기 때문입니다.비밀 정보는 무조건 삭제됩니다.
--no-redact는 PII 마스킹만 비활성화하며 자격 증명 마스킹은 절대 비활성화하지 않습니다. 공급자가 오류 본문에 API 키를 그대로 반환하더라도 보고서에 들어갈 수 없습니다. 정확히 그 상황에 대한 테스트가 있습니다.기본적으로 어떤 것도 머신 밖으로 나가지 않습니다. 선택적 LLM 주장 평가기는 구성하지 않으면 꺼져 있으며,
validate-config는 구성이 이를 켤 때 경고합니다.보고서 파일은
0600권한으로 작성되며, 임시 파일에 쓴 후 이름을 변경합니다.샘플은 제한됩니다. 100,000개 리드 캠페인이 100,000줄을 출력할 수 없습니다.
성능
작업량 | 시간 |
데모 (20개 리드) | 0.02 s |
10,000개 리드 | 0.28 s |
100,000개 리드 | 3.0 s, 약 300 MB 최대 |
행은 한 번에 모두 읽지 않고 스트리밍됩니다. 페이지네이션, 재시도, 발신자 동시성, 출력 크기는 모두 제한됩니다.
개발
git clone https://github.com/katekruger/campaignpreflightplugin
cd campaignpreflightplugin
uv sync --all-extras
uv run pytestuv run ruff format . # format
uv run ruff check . # lint
uv run mypy # typecheck, strict
claude plugin validate . --strict # manifests
uv run python scripts/generate_rules_doc.py --check # docs/rules.md is current
./scripts/bump-version.sh --check # version fields agree
uv run python scripts/build_plugin.py # dist/campaign-preflight.plugin패키지 자체에는 런타임 의존성이 없습니다. dev 그룹은 테스트 스위트, 린터, 그리고 테스트 오라클로만 사용되는 두 라이브러리(선택적 Instantly 공급자용 httpx와 번들된 YAML 파서를 차등 테스트하기 위한 PyYAML)를 위해 존재합니다.
이유를 알기 전까지는 실수처럼 보이는 규칙들은 CLAUDE.md에 문서화되어 있습니다.
로드맵
동일한 읽기 전용 인터페이스 뒤의 추가 공급자 (Smartlead, HubSpot Sequences, Apollo)
도메인 평판 및 DNS 레코드 검사 (SPF, DKIM, DMARC 정렬)
PR 주석과 함께 CLI를 감싸는 GitHub Action
기준선 비교: 두 보고서를 비교하여 마지막 실행 이후 변경된 사항 표시
세그먼트별 임계값, 하나의 구성으로 여러 모션을 처리 가능
기여
규칙은 작고 순수하며 독립적으로 테스트 가능합니다. 새 규칙은 보통 클래스 하나, docstring 하나, 그리고 몇 개의 테스트로 구성됩니다. 자세한 내용은 CONTRIBUTING.md와 CODE_OF_CONDUCT.md를 참조하세요.
보안
취약점은 비공개로 보고해 주세요: SECURITY.md. 데이터가 없을 때 PASS를 반환한 규칙은 보안 문제로 간주됩니다.
라이선스
MIT. LICENSE 참조.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityFmaintenanceA Model Context Protocol server that provides read-only access to Mailchimp's Marketing API for comprehensive email marketing data retrieval.3822811MIT
- FlicenseNot gradedqualityDmaintenanceA utility MCP server providing 10 specialized tools for newsletter content preparation and optimization, including subject line generation, HTML-to-text extraction, read time estimation, and email validation. Enables newsletter operators, developers, and content teams to automate pre-send workflows and audit newsletter issues through natural language interactions.
- AlicenseBqualityAmaintenanceLocal-first production-readiness MCP server for AI-built apps. It runs read-only checks, produces an evidence-based readiness score, and guides fixes before launch.95Apache 2.0
- FlicenseNot gradedqualityAmaintenanceRead-only MCP server that performs deterministic local preflights of agent-payment boundary documents and x402 v2 PaymentRequired JSON, and prepares unsubmitted public quote-request drafts without network calls or fund movement.
Related MCP Connectors
Render markdown into email-safe HTML, lint drafts for deliverability problems, and preview emails.
Read-only MVR preflight for trust, permission, evidence gaps, and African market-entry readiness.
Send transactional email, run campaigns, manage contacts and automations, audit deliverability.
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/katekruger/campaignpreflightplugin'
If you have feedback or need assistance with the MCP directory API, please join our Discord server