Skip to main content
Glama

slop-scorer-mcp

Un servidor MCP que le dice a un agente de codificación, con citas, qué partes de una base de código o de una página web renderizada se leen como salida de plantilla generada por máquina, y devuelve la edición exacta que eliminaría cada una.

No hay ningún modelo involucrado en este servidor. Cada hallazgo cita un archivo y un número de línea, o un selector CSS y un valor de estilo calculado, que puedes ir a comprobar tú mismo. Setenta reglas, todas ellas datos, todas ellas con su propia refutación.

claude mcp add slop-scorer -- npx -y github:Yuve21/slop-scorer-mcp

Node 20 o superior y nada más. Aún no está en npm, así que esa línea instala desde este repositorio; el primer lanzamiento compila y tarda aproximadamente un minuto. El detalle completo, y las otras dos formas de acceso, están en Instalación.


Por qué existe esto

La mitad interesante no es la detección. Es list_rules, que devuelve todo el corpus para que un agente pueda leer qué no debe producir antes de producir nada.

La detección es una carrera que finalmente se pierde: los generadores mejoran, los indicios se degradan, y un corpus de indicios es un activo que se deprecia. La prevención no se degrada, porque un agente que lee primero el corpus escribe trabajo sobre el que el corpus no se dispara. Es el único bucle aquí que se fortalece cuanto más se usa.

Related MCP server: Sensory-Grounding MCP

Lo que no hará

Esto importa más que la lista de funciones, así que va primero.

  • Nunca dice que una persona haya usado IA. Cada frase que puede emitir tiene la misma gramática: el sujeto es el servidor, el objeto es el artefacto, el verbo es algo que el servidor hizo. "Comprobamos este artefacto contra 15 reglas deterministas y 4 coincidieron, con una cobertura del 88%." No "esto es IA". El formateador no puede expresar la otra frase, y una prueba en @slop/core hace fallar la compilación si una frase prohibida aparece en el código fuente.

  • La abstención es un resultado, no un fallo. status es assessed, inconclusive (miramos y no publicaremos un número) o not_assessed (no miramos). Ambas abstenciones llevan score: null y un motivo codificado. No son puntuaciones bajas ni son certificados de buena salud. Decide según status, nunca según score.

  • La puntuación se detiene en 99. No hay ninguna combinación de evidencia que alcance la certeza.

  • Una lectura incompleta retiene la puntuación por completo. Una página que solo se renderizó a medias se ve exactamente como una página limpia, y publicar un número con seguridad sobre una lectura parcial sería lo más deshonesto que este servidor podría hacer.

  • No publica ninguna cifra de precisión, en ningún sitio. packages/core/test/no-claims.test.ts escanea cada archivo fuente distribuido y cada README en cada ejecución de pruebas y hace fallar la compilación si aparece una. Una afirmación de precisión sobre una inferencia es una afirmación que requiere fundamentación según la sección 5 de la FTC Act (In re Workado, 2026), así que la única forma defendible de mantener una es calcularla a partir de un corpus designado en el momento de la prueba. Si quieres un número, ejecuta npm run backtest y lee el tuyo propio.

  • Nunca escribe un archivo. Sin escritura en el sistema de archivos, sin exec, sin solicitud de acceso de escritura en ningún lugar del paquete. Las correcciones vuelven como datos para que tu agente las aplique bajo tu flujo de aprobación normal.

Instalación

slop-scorer-mcp todavía no está en el registro npm, así que cada comando aquí instala desde este repositorio. Eso funciona bien, con una advertencia que vale la pena leer antes de que decidas que la instalación se rompió.

El primer lanzamiento compila desde el código fuente. Medido en frío, con la caché de npm vacía: 69 segundos. La mayoría de los clientes MCP dan a un servidor 30 segundos para responder, así que la primera conexión puede informar connection timed out aunque no haya nada malo. Vuelve a conectar, o calienta la caché primero:

npx -y github:Yuve21/slop-scorer-mcp   # wait for "listening on stdio", then Ctrl-C

Cada lanzamiento posterior sale de la caché y es inmediato.

Claude Code

claude mcp add slop-scorer -- npx -y github:Yuve21/slop-scorer-mcp

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json en macOS, %APPDATA%\Claude\claude_desktop_config.json en Windows. Reinicia la aplicación después.

{ "mcpServers": { "slop-scorer": { "command": "npx", "args": ["-y", "github:Yuve21/slop-scorer-mcp"] } } }

Cursor

~/.cursor/mcp.json de forma global, o .cursor/mcp.json por proyecto. El mismo bloque. Recarga la ventana.

{ "mcpServers": { "slop-scorer": { "command": "npx", "args": ["-y", "github:Yuve21/slop-scorer-mcp"] } } }

Desde un checkout

Usa esto si vas a cambiar una regla y ver cómo se dispara.

git clone https://github.com/Yuve21/slop-scorer-mcp
cd slop-scorer-mcp
npm install                                            # `prepare` builds it for you
npm run install:local --workspace=packages/mcp-server

Esa última línea registra el binario compilado con claude mcp add mediante ruta absoluta. Si la CLI de claude no está en tu PATH, imprime el bloque JSON para que lo pegues a mano en lugar de fallar silenciosamente.

Cuando esté en npm

claude mcp add slop-scorer -- npx -y slop-scorer-mcp

Sin paso de compilación, sin arranque en frío, porque un tarball del registro se distribuye compilado. Esto devuelve 404 hoy.

Cómo funciona la instalación desde GitHub

npx -y github:... resuelve la RAÍZ del repositorio, y npm no tiene forma de apuntar una especificación git a un subdirectorio. Así que el package.json raíz aquí lleva un bin (una única entrada, que es lo que permite a npx elegir un ejecutable), un script prepare (el único hook del ciclo de vida que npm ejecuta para una dependencia git: prepack no se ejecuta ahí), una lista files que nombra packages/mcp-server/dist (porque dist/ está en gitignore y npm recurre a .gitignore al empaquetar, lo que enviaría el tarball con el binario eliminado), y las dos dependencias de ejecución que el bundle de esbuild deja externas. Un .npmignore raíz se sitúa junto a ellos para que .gitignore nunca se consulte en absoluto.

scan_ui necesita un navegador

npx playwright install chromium

Sin él, scan_ui devuelve status: "not_assessed" y dice por qué. No recurrirá a leer el HTML del servidor: una lectura solo con fetch produce hallazgos con confianza sobre un documento que nadie ve, que es como una comprobación de encabezados informó una vez "esta ruta tiene 0 H1" para una ruta cuyo encabezado no existe hasta la hidratación.


Las cinco herramientas

categoría

qué hace

list_rules

Todo el corpus, compacto. Lee antes de generar.

scan_codebase

Análisis estático de un checkout, más historial de git.

scan_ui

Renderiza una URL o un servidor de desarrollo en Chromium y mide el documento renderizado.

propose_fixes

Vuelve a escanear y devuelve cada hallazgo como una edición precisa y con advertencias.

verify_fix

Vuelve a escanear y pone los conjuntos de hallazgos antes y después lado a lado.

list_rules

Setenta reglas repartidas en dos corpus: 51 web, 19 código. Compacto por defecto, porque una herramienta que pide ser llamada antes de que generes cualquier cosa no puede costar una quinta parte de una ventana de contexto pequeña.

index         every rule, one line: id | family | polarity/severity | weight | rationale
fullEntries   why it reads as generated, the counter-evidence that rebuts it, how to avoid it
retrieval     a sentence on every response saying how to get what was left out
modality: "web" | "code" | "all"                     optional
family:   e.g. "agent-artifact"                      optional
ruleIds:  ["craft.no-og-image", ...]                 full entries for these only
verbose:  true, full entries for every rule          costs roughly 18k tokens

El patrón habitual después de un escaneo es ruleIds: [...the ids that fired], que cuesta unos cientos de tokens y devuelve exactamente la refutación y la nota de prevención que necesitas para actuar en consecuencia.

scan_codebase

path:        absolute path to the repository root
include:     optional patterns, e.g. ["src/**/*.ts"]
readHistory: read git history for the commit-shape rules (default true)
maxFiles:    cap on files walked (default 5000)

Una lectura real, producida apuntando este servidor a su propio checkout. Nada aquí está tecleado a mano: son los bytes de la respuesta, ligeramente recortados para ajustar la longitud. Observa que encuentra cosas en nosotros.

SLOP RECEIPT  20 / 99   band: few known signals
corpus code-corpus-2026.09  |  coverage 100%  |  families fired 2
evidence kind: deterministic  |  detectors: code.static-rules

We checked this artifact against 19 deterministic rules from code-corpus-2026.09 and 4
matched, on 100% coverage. That places it in the "few known signals" band at 20 of 99.
Every match below cites what we read and where.

     15  base rate before any evidence
    +26  scaffold.placeholder-markers  [scaffold-residue / medium]  -> 41
         Unfilled placeholders left in shipped source
         evidence: line packages/detectors-code/src/artifact.ts:73 = "lorem ipsum"
                   (expected "a real value")
         evidence: line packages/detectors-code/src/artifact.ts:109 = "TODO: implement"
                   (expected "a real value")
         evidence: line packages/detectors-code/src/suppression.ts:18 = "lorem ipsum"
                   (expected "a real value")
         ... and 4 more, 5 counted toward the weight
         caveat: TODOs are a normal and healthy way to record known gaps, and a mature
                 codebase carries plenty. Markers that name an owner or a ticket are
                 excluded as tracked work. Suppressed by suppress.self-defining-pattern:
                 19 match(es) were withdrawn as self-referential: the cited lines in
                 packages/detectors-code/src/scan.ts are the DEFINITION of the patterns
                 that matched them, not uses of them.
    +23  verify.tautological-tests  [verification-floor / high]  -> 64
         Tests that cannot fail
         evidence: file packages/detectors-code/test/corpus/index.ts
                   = "93 lines, 0 assertions" (expected "at least one assertion")
         evidence: file packages/detectors-web/test/corpus/index.ts
                   = "60 lines, 0 assertions" (expected "at least one assertion")
         caveat: A deliberate smoke test that only checks a module imports without
                 throwing looks like this, and an assertion helper the scanner does not
                 recognise reads as zero assertions.
    -42  counter.rationale-comments  [counter-evidence / counter]  -> 22
         Comments that record a reason, not a restatement
         evidence: line packages/core/src/assessment.ts:61 = "We read the artifact cleanly
                   and it carried no declared provenance either way. ABSENCE OF PROVENANCE
                   IS NOT EVIDENCE OF GENERATION."
         ... and 3 more, 4 counted toward the weight
         caveat: A rationale comment can be copied along with the code it explains, and an
                 agent prompted to explain its reasoning will write plausible ones. The
                 signal is real but it is not proof.
     -2  counter.real-test-coverage  [counter-evidence / counter]  -> 20
         Tests dense enough to actually fail
         evidence: metric "26 test files against 63 source files"
                   = "606 assertions, 0 tautologies"

     20  TOTAL (base 15 + 4 contribution(s))

FAMILY CAPS
  Scaffold residue             +26 pts   logit 1.37 of 1.60 allowed
  Verification floor           +23 pts   logit 1.35 of 0.96 allowed  AT CAP
  Global counter-evidence      logit -2.00  AT CAP  (bypasses family caps)

WHAT WOULD CHANGE THIS SCORE
  -26  scaffold.placeholder-markers: Fail the build on the placeholder strings your
       scaffold ships with. They are the ones nobody notices.
  -23  verify.tautological-tests: Mutation-test the test: break the code it covers and
       confirm it goes red. If it stays green, delete it or fix it.

A high score means this artifact resembles generated-template output. It is not proof that
a tool made it, and it is not a judgement of the person who made it.

Cuatro cosas en esa salida merecen señalarse, porque son el diseño:

  1. La contraevidencia resta. Dos de las cuatro coincidencias argumentan a favor del artefacto y juntas valen más que todo lo que hay en contra. Un corpus que solo pudiera acusar puntuaría todo código cuidadoso como generado.

  2. Las familias están limitadas. "Verification floor" contribuyó 23 puntos y está marcado como AT CAP, así que ningún grupo correlacionado de indicios puede sustentar un veredicto por sí solo.

  3. El recibo cuadra. La tasa base más cada contribución impresa es igual a la puntuación impresa, en enteros, exactamente. Puedes volver a calcular el número a mano.

  4. Un supresor se disparó y lo dijo. Diecinueve coincidencias de marcador de posición fueron retiradas porque las líneas que coincidieron son la tabla de patrones que define el patrón. Un supresor de fase dos puede retirar evidencia sobre el detector en lugar de sobre el artefacto, pero tiene que nombrar la regla, el archivo y el motivo, en el recibo, donde puedas verlo.

En la respuesta real, cada valor copiado del artefacto escaneado está envuelto en una valla untrusted y el payload cierra con una advertencia de inyección de prompt, porque un escáner que cita el código fuente de un extraño en el contexto de un agente es un vector de inyección. Las vallas se han eliminado arriba solo para que el ejemplo se lea.

scan_ui

url:            https://example.com/pricing
port:           3000                      (instead of url, for a local dev server)
viewportWidth:  default 390
viewportHeight: default 844

Renderiza en Chromium y mide el documento renderizado: huellas del constructor, lenguaje visual por defecto, defectos de nivel artesanal, uniformidad estructural y de movimiento, indicios en el texto. Un hallazgo real:

   +7  css.crushed-tracking  [visual-default / medium]  -> 34
       Headline letter-spacing is crushed at a heavy weight
       evidence: css letter-spacing on h1 = "-0.04em at weight 800"
                 (expected "-0.02em or looser at weight 700+")
       caveat: Some faces genuinely want negative tracking at display size, and a
               type-literate designer may choose exactly this. It is a taste signal,
               not a provenance signal.

Una capacidad falta en esta compilación y falta a propósito. El texto renderizado dentro de una imagen no se recupera aquí: el recuperador vive en una mitad privada del proyecto, así que packages/ocr-text en este repositorio siempre se abstiene, con un motivo declarado adjunto a cada imagen sobre la que se le preguntó. Las tres reglas imgtext.*, por lo tanto, no pueden dispararse en una ejecución real de scan_ui. Permanecen en list_rules (el consejo de no enterrar tu texto en un JPEG vale la pena leerlo de todas formas) y todavía puntúan los artefactos congelados del corpus, así que los números archivados no se mueven. Esto está escrito en lugar de omitirse silenciosamente porque una imagen no leída no es una imagen sin palabras en ella.

propose_fixes

Vuelve a escanear el objetivo y devuelve cada hallazgo como una propuesta, agrupada por familia y dividida en cuatro vías para que tu agente pueda presentarla como "aplica estas N, omite estas M".

categoría

significado

readyToApply

replace_range, insert, replace_file. Localizador y reemplazo, ambos determinados.

needsConfirmation

delete_file. El único tipo destructivo, y su propia categoría para que pueda restringirse.

needsSourceLocation

ui_change. Selector, propiedad y valores exactos; el archivo que los declara no es posible conocer desde una lectura renderizada.

decideYourself

manual. Una persona decide. El localizador y cómo se ve una buena respuesta, y ningún valor inventado.

{
  "id": "agent.instruction-file-committed#1",
  "ruleId": "agent.instruction-file-committed",
  "applicability": "confirm",
  "destructive": true,
  "blastRadius": "file",
  "remediation": {
    "kind": "delete_file",
    "path": "CLAUDE.md",
    "bytes": 4200,
    "summary": "Remove CLAUDE.md from the repository and from the index.",
    "rebuttal": "This says how the repository was worked on, not who wrote any given line.",
    "doNotApplyIf": "this file is a deliberate part of how the team works. In that case keep it and say so in the README, which answers the finding without deleting anything."
  }
}

La mayoría de las reglas proponen manual a propósito. Un título de página, una meta descripción, un atributo alt y una paleta de marca son cosas que una máquina puede producir al instante, y todas ellas cuya producción por máquina es el defecto que este corpus mide. El texto alt generado es el caso más claro: satisface al verificador y le dice a un usuario de lector de pantalla, con confianza, algo sobre una imagen que nadie miró. Así que esas reglas señalan la brecha y se detienen.

Dos restricciones se aplican en todas partes en esta herramienta:

  • Solo una lectura determinista puede proponer un parche. Cuando un detector se abstiene de la certeza, la corrección no puede afirmarla.

  • Cada corrección lleva la refutación de la propia regla y un doNotApplyIf explícito, inyectado desde el falsePositiveNote de la regla para que la corrección y el argumento en contra nunca puedan separarse.

  • La contraevidencia nunca es subsanable. Un hallazgo en contra argumenta a favor del artefacto. El corpus lanza una excepción al cargar si alguien adjunta una corrección a uno.

verify_fix

Before: 9 finding(s). After: 6. 3 no longer present, 6 still present, 0 newly present.
Score moved by -14 point(s).

No informa de éxito. noLongerPresent es una lista de reglas que ya no coinciden en esos localizadores, que es un hecho sobre un nuevo escaneo y no una afirmación de que un problema se resolvió. newlyPresent se indica primero y establece regression: true, porque un cambio que resuelve dos hallazgos e introduce uno ha roto algo, y un verificador que informara del balance llamaría a eso una mejora. Si no hay una lectura anterior del objetivo guardada en esta sesión, lo dice en lugar de comparar contra nada: una primera ejecución nunca es un visto bueno.


El bucle

escanea, propone, aplica, verifica. El informe nunca fue el objetivo; el cambio lo era.

1. scan_codebase / scan_ui   what is there, with a locator on every claim
2. propose_fixes             the same findings as precise, caveated edits
3. YOUR agent applies them   with its own edit tools, under the user's normal approval
4. verify_fix                re-scan, and show which findings are no longer present

El paso 3 deliberadamente no es trabajo de este servidor. Tu agente ya tiene herramientas de edición, un prompt de aprobación y un usuario que confía en ellas. Una segunda copia, peor, de esa maquinaria dentro de un servidor MCP sería más código, más riesgo y menos control.

Qué hay en este repositorio

paquete

qué es

packages/mcp-server

El servidor. Cinco herramientas, el binario stdio y el paquete publish-shape.

packages/core

El contrato de reglas, el motor de puntuación, el recibo y el banco de calibración.

packages/detectors-code

El corpus de código: 19 reglas, más 16 repositorios etiquetados (10 humanos, 4 generados, 2 sintéticos).

packages/detectors-web

El corpus web: 51 reglas, más 9 páginas etiquetadas (5 humanas, 4 generadas).

packages/ocr-text

El sustituto de imagen-texto que se abstiene, descrito en scan_ui.

El paquete npm publicado es autocontenido: npm run build empaqueta los tres paquetes internos del workspace en dist/bin.js y dist/index.js con esbuild e incorpora sus declaraciones de tipos, de modo que nada en el tarball apunte a un paquete que nunca se publicó. @modelcontextprotocol/sdk y zod siguen siendo dependencias externas reales; playwright sigue siendo una dependencia peer opcional.

Constrúyelo tú mismo

npm install
npm run build      # tsc -b, then the esbuild bundle
npm test           # the rule suite, both calibration corpora, the security and FTC guards
npm run backtest   # the gate: replay both frozen corpora and diff against the baseline

npm test nunca lanza un navegador. Las pruebas web se ejecutan contra artefactos almacenados, que es también lo que hace que la calibración sea reproducible.

Contribuciones

Lee primero CONTRIBUTING.md. La versión corta: una regla en este repositorio es una acusación con aritmética detrás, así que el listón es npm run backtest, no «las pruebas están en verde». Cada regla incluye un caso positivo en el que debe dispararse y un caso mutado en el que no debe hacerlo, y la meta-suite ejecuta ambos en cada ejecución de pruebas. Añadir un miembro al corpus con procedencia declarada y comprobable es una contribución mayor que añadir una regla.

Licencia

MIT. Ver LICENSE.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

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/Yuve21/slop-scorer-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server