campaign-preflight-mcp
Preflight de campañas
Campaign Preflight es un linter de solo lectura para campañas salientes. Detecta problemas de configuración, datos de contacto, personalización, supresión, programación y remitentes antes del lanzamiento.
Qué hace
Todos los equipos de salientes han enviado una campaña con un error. Alguien que se dio de baja recibió el correo de todos modos. Una secuencia siguió haciendo seguimiento después de que el prospecto respondiera. Un campo de combinación nunca se combinó y doscientas personas recibieron "Hola {{first_name}}".
Te enteras después de que se envía.
Campaign Preflight ejecuta 76 comprobaciones deterministas sobre la configuración de una campaña, los leads, el texto, el calendario, los remitentes y la exposición a supresión, y devuelve una decisión de preparación con evidencia para cada hallazgo. Nunca escribe en tu proveedor y no puede activar nada.
Lo que no hace, de entrada y no al final:
No garantiza la entregabilidad. Comprueba configuración y datos, no la colocación en la bandeja de entrada, y nunca inventa una puntuación de entregabilidad.
No ofrece asesoramiento legal. Las comprobaciones de región, dominio y exclusión comparan una campaña con tu propia política configurada — no con GDPR, CAN-SPAM o CASL.
No verifica buzones. Las comprobaciones de direcciones son solo de sintaxis. Sin DNS, sin SMTP.
No reemplaza las salvaguardas de tu proveedor. Mantenlas activadas.
Los resultados son una instantánea en un momento dado. Una campaña que pasó a las 09:00 puede editarse a las 09:05.
Más detalle en docs/limitations.md.
Related MCP server: Newsletter Tools
"Lo comprobamos y está bien" ≠ "no pudimos comprobarlo"
Un comprobador que no puede distinguir entre ambos es peor que ningún comprobador, porque convierte un error de permisos en una luz verde.
Campaign Preflight hace que la distinción sea estructural. Cada lectura del proveedor devuelve datos más la razón por la que existen o no, y cada regla declara los datos que necesita. Si esos datos no están disponibles, el motor cortocircuita la regla a UNKNOWN antes de que pueda ejecutarse. Las reglas no pueden optar por no participar.
Situación | Resultado |
Lista de supresión leída, nadie coincide |
|
No se proporcionó lista de supresión |
|
El endpoint de supresión devolvió 403 |
|
Cero leads en la campaña |
|
Endpoint de leads inalcanzable |
|
Hay cuatro veredictos, no dos: READY, READY_WITH_WARNINGS, NOT_READY e INCOMPLETE.
Requisitos
Python 3.9 o más reciente. Esa es toda la lista.
El paquete no tiene dependencias de ejecución — no importa nada fuera de la biblioteca estándar. httpx es un extra opcional necesario solo para el proveedor en vivo de Instantly, detrás de una importación diferida.
El mínimo de 3.9 es deliberado, y deliberadamente más bajo de lo que podrías esperar. Es el intérprete más antiguo que el plugin puede encontrar en la máquina de un usuario, y como no hay dependencias, nada lo obliga a ser más alto. CI ejecuta 3.9 a 3.13 más un trabajo de intérprete desnudo que no instala nada en absoluto, en Linux, macOS y Windows.
Esa combinación es lo que permite que el plugin se ejecute sin paso de instalación: usa el python3 que ya esté allí.
Instalación
Como plugin de Claude (marketplace)
/plugin marketplace add katekruger/campaignpreflightplugin
/plugin install campaign-preflightEl repositorio es su propio marketplace: .claude-plugin/marketplace.json se encuentra en la raíz junto al manifiesto del plugin.
Como plugin de Claude (checkout local)
git clone https://github.com/katekruger/campaignpreflightplugin/plugin marketplace add ./campaignpreflightplugin
/plugin install campaign-preflightComo CLI
pipx install campaign-preflightO directamente desde un checkout, sin instalar nada en absoluto:
PYTHONPATH=src python3 -m campaign_preflight.cli demoComo servidor MCP
claude mcp add campaign-preflight -- campaign-preflight-mcpSeis herramientas de solo lectura. Nada que pueda activar, editar, importar o enviar. Configuración para Claude Code y Claude Desktop: docs/mcp.md.
Inicio rápido
campaign-preflight demoSin clave API. Sin red. Sin configuración.
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.Observa el último hallazgo. Un remitente no informa un límite diario, por lo que la capacidad total no se puede sumar. La mayoría de las herramientas sumarían los remitentes que sí informan uno y lo llamarían un número. Esta dice que no lo sabe — y reduce la confianza de HIGH a MEDIUM por eso.
Esa distinción es toda la idea.
Comprobando tu propia campaña
Una vez instalado el plugin, descríbelo en lenguaje natural:
Comprueba esta campaña antes de que la envíe.
Aquí está mi lista de leads — ¿algo mal con ella? (pegar o subir)
Voy a enviar una secuencia de 3 correos a 200 personas, 80 al día, de lunes a viernes de 9 a 5 hora del Este. ¿Está bien?
Hay tres formas de entrar, y ninguna necesita una cuenta:
Tienes | Qué sucede |
Un archivo (subido o en disco) | Se comprueba directamente. |
Una lista pegada o algo de texto | Se escribe en un archivo temporal, se comprueba y luego se limpia. |
Solo una descripción | El archivo de campaña se construye a partir de lo que dices, se te muestra y luego se comprueba. |
Cualquier cosa que no sepas se deja en blanco en lugar de adivinarse — un campo en blanco vuelve como "no se pudo comprobar", que es la respuesta honesta.
Desde archivos, en la línea de comandos
campaign-preflight check \
--campaign examples/clean_campaign/campaign.yaml \
--leads examples/clean_campaign/leads.csv \
--suppressions examples/clean_campaign/suppressions.csvTres ejemplos trabajados se incluyen con el repositorio, uno por veredicto:
Ejemplo | Veredicto | Salida |
|
| |
|
| |
|
|
En CI
campaign-preflight check --campaign campaign.yaml --leads leads.csv --fail-on blockerLos códigos de salida llevan el veredicto, por lo que esto se integra directamente en un pipeline. Ver docs/ci.md.
Qué hay dentro
La raíz del repositorio es el plugin. No hay una segunda copia del árbol.
.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 packagerHabilidades
Habilidad | Úsala para |
| Comprobar una campaña real que proporciones — un archivo, un pegado o una descripción. |
| Ver el comprobador ejecutarse con datos de muestra incluidos. |
| Qué reglas existen, qué prueba cada una y cómo reajustarlas o desactivarlas. |
Los límites son deliberados: cada descripción nombra su propia situación y apunta a su vecina, para que un casi-acierto aterrice en un lugar recuperable.
Qué comprueba
76 reglas en siete categorías. Catálogo completo: docs/rules.md.
Categoría | Reglas | Ejemplos |
Campaña | 10 | Detener al responder desactivado, volumen diario por encima del umbral, sin ventana de envío, fechas que no dejan días de envío |
Contactos | 15 | Direcciones mal formadas, duplicados (exactos y con plegado de mayúsculas), buzones de rol, valores de marcador de posición, caracteres de control y bidireccionales, inyección de fórmulas en hojas de cálculo |
Supresión | 8 | Contactos y dominios en tu lista de supresión, clientes existentes, direcciones internas, competidores, regiones restringidas — y si la comprobación de supresión pudo ejecutarse siquiera |
Personalización | 13 | Tokens de combinación sin renderizar, un saludo dirigido a la persona equivocada, una empresa que no es la suya, afirmaciones no respaldadas por su propia evidencia, investigación desactualizada, texto de inyección de prompts extraído de la página de un objetivo |
Texto | 13 | Asunto vacío en el primer paso, enlaces rotos, marcadores |
Programación | 9 | Zona horaria inválida, envío en fin de semana, cero días activos, una ventana que termina antes de empezar, transiciones de horario de verano dentro de la campaña |
Remitentes | 8 | Buzones por debajo de tu umbral de salud, estados de error, volumen que excede la capacidad — y |
Pregunta a la herramienta sobre cualquiera de ellos:
campaign-preflight rules list --category suppression
campaign-preflight rules explain senders.aggregate_capacityLo que deliberadamente no comprueba
No hay regla de palabras spam. "Gratis" y "actúa ahora" no son evidencia de nada, y publicar esa lista te entrenaría para ignorar la herramienta. Las reglas que sí son juicios — longitud del texto, número de enlaces, artefactos de generación — están marcadas como heuristic, etiquetadas como tales en cada informe, y nunca son bloqueadores por defecto.
Configuración
Campaign Preflight se ejecuta con valores predeterminados sensatos y sin archivo de configuración. Añade uno cuando tus umbrales difieran, o para activar las comprobaciones que dependen de tus propias listas de dominio y región.
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.yamlLa validación es estricta a propósito: un id de regla desconocido o una opción desconocida es un error grave, no una advertencia. Un error tipográfico que desactiva silenciosamente una comprobación de seguridad es peor que no tener configuración.
Referencia completa: docs/configuration.md.
Por qué importa el solo lectura
Campaign Preflight no tiene ninguna ruta de código que escriba. No es "elegimos no hacerlo" — no hay nada que llamar.
El proveedor de Instantly enruta cada solicitud a través de un transporte que comprueba
(method, path)contra una lista de permitidos explícita y lanza una excepción antes de que la solicitud salga del proceso. La comprobación está por debajo del cliente y por debajo del proveedor, por lo que un cambio futuro de código que añada unPATCHfalla ruidosamente en lugar de editar silenciosamente tu campaña.Dos guardas se ejecutan en el momento de la importación: la lista de permitidos no puede contener
PUT,PATCH,DELETE,HEADuOPTIONS, yPOSTestá permitido solo para una ruta exacta (/leads/list, que es la forma documentada de Instantly para una lectura filtrada).El servidor MCP se niega a iniciarse si alguna herramienta registrada tiene un verbo mutador en su nombre o no se declara de solo lectura.
tests/contract/test_instantly_transport.pyejercita la matriz completa de método × ruta más cada endpoint mutador documentado. Un fallo allí es un incidente de seguridad, no un fallo de prueba.
Esto es lo que hace seguro entregar una campaña en vivo a un agente. Obtiene el análisis y ninguna de la autoridad.
Lo que nunca hará
Activar, pausar, reanudar o programar una campaña
Crear, actualizar, mover, fusionar o eliminar un lead
Añadir o eliminar de una lista de supresión
Enviar, responder o reenviar un correo electrónico
Modificar cualquier cosa en tu plataforma de envío
No existe ninguna ruta de código hacia ninguna de estas acciones, y dos salvaguardas independientes — la lista blanca de transporte y la aserción de arranque de MCP — fallan de forma segura si alguna vez se añade una.
Exit codes
Code | Meaning |
|
|
|
|
|
|
|
|
| Error de configuración o de entrada |
| Error de proveedor o de autenticación |
| Error interno inesperado |
--fail-on none|warning|high|blocker eleva el umbral a partir del cual un veredicto se convierte en una salida distinta de cero. Nunca cambia el veredicto en sí. INCOMPLETE no se silencia mediante un umbral de gravedad: una comprobación que no pudo ejecutarse es un problema distinto de un hallazgo de baja gravedad.
La puntuación se publica, no se oculta
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 otherwiseDe ello se derivan cuatro cosas, y cada una tiene una prueba:
Un bloqueador siempre produce
NOT_READY. El número no puede anularlo.UNKNOWNno descuenta nada. Una caída del proveedor no debe parecer una mala campaña: en su lugar, reduce la confianza.NOT_APPLICABLEno afecta a nada.Cada deducción se detalla.
--verboseimprime la aritmética para que puedas comprobarla a mano.
Los pesos y la lista de reglas críticas son configurables: docs/configuration.md.
Arquitectura
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:#fffEl contexto es un modelo Pydantic congelado, por lo que «una regla nunca muta su entrada» se aplica mediante el sistema de tipos en lugar de mediante revisión. El comportamiento específico del proveedor vive completamente detrás de la interfaz del proveedor.
Diseño completo y modelo de amenazas: docs/architecture.md.
Privacidad
Redactado por defecto. Las partes locales del buzón se enmascaran (
m**********s@stonebridge.example.com); los dominios se conservan, porque un dominio es lo que hace que un hallazgo de supresión sea accionable.Los secretos se eliminan incondicionalmente.
--no-redactdesactiva el enmascaramiento de PII, nunca el de credenciales. Un proveedor que devuelva tu clave de API en un cuerpo de error no puede hacer que llegue a un informe; hay una prueba exactamente para eso.Nada sale de tu máquina por defecto. El evaluador opcional de afirmaciones LLM está desactivado a menos que lo configures, y
validate-configte advierte cuando una configuración lo activa.Los archivos de informe se escriben con
0600, en un archivo temporal y luego se renombran.Las muestras están limitadas. Una campaña de 100,000 leads no puede emitir 100,000 líneas.
Rendimiento
Carga de trabajo | Tiempo |
Demo (20 prospectos) | 0.02 s |
10,000 prospectos | 0.28 s |
100,000 prospectos | 3.0 s, ~300 MB pico |
Las filas se transmiten en flujo, no se tragan de golpe. La paginación, los reintentos, la concurrencia del remitente y el tamaño de salida están todos limitados.
Desarrollo
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.pluginEl paquete en sí no tiene dependencias de ejecución; el grupo de desarrollo existe para la suite de pruebas, los linters y dos bibliotecas utilizadas solo como oráculos de prueba: httpx para el proveedor opcional de Instantly y PyYAML para probar diferencialmente el analizador YAML incluido.
Las convenciones que parecen errores hasta que sabes por qué están escritas en CLAUDE.md.
Hoja de ruta
Proveedores adicionales detrás de la misma interfaz de solo lectura (Smartlead, HubSpot Sequences, Apollo)
Comprobaciones de reputación de dominio y registros DNS (alineación SPF, DKIM, DMARC)
Una GitHub Action que envuelve la CLI con anotaciones de PR
Comparación de línea base: comparar dos informes y mostrar qué cambió desde la última ejecución
Umbrales por segmento, para que una configuración pueda cubrir varios movimientos
Contribuciones
Las reglas son pequeñas, puras y comprobables de forma independiente: una nueva suele ser una clase, un docstring y un puñado de pruebas. Consulta CONTRIBUTING.md y CODE_OF_CONDUCT.md.
Seguridad
Informa de vulnerabilidades de forma privada: SECURITY.md. Una regla que devolvió PASS cuando faltaban los datos cuenta como un problema de seguridad.
Licencia
MIT. Consulta 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