Public MCP + RAG · Parte 1

Cómo hacer públicos los datos de tu app y prepararlos para producción con MCP y RAG

Una guía práctica para ingenieros y PMs que quieren exponer datos públicos de sus apps de forma segura mediante MCP y RAG, con allowlists, caché, controles de costos y una lista de verificación para producción.

21 min de lectura

TL;DR

  • Hacer “públicos” los datos de una app no es lo mismo que volcar tu base de datos en un vector store. Es una allowlist deliberada de documentos, catálogos, registros de cambios, páginas de precios y APIs de lectura con alcance limitado en los que agentes y personas pueden confiar.
  • El patrón de producción que funciona en 2026 tiene tres capas: contenido estático fácil de descubrir (llms.txt, markdown, sitemaps), un servidor MCP para recursos estructurados y herramientas de alcance limitado, y un servicio RAG para búsqueda semántica sobre el mismo corpus público.
  • La seguridad viene de la separación: una ruta de lectura pública, una ruta de escritura autenticada, scopes por herramienta y filtros de recuperación que nunca acceden a filas privadas. OAuth 2.1 es para endpoints MCP protegidos, no para todo.
  • El control de costos combina varias medidas, no un solo truco: guarda en caché los embeddings y los conjuntos de recuperación, usa la caché de prompts del proveedor para prompts de sistema estables, aplica caché semántica a preguntas frecuentes, enruta consultas sencillas a modelos más pequeños y limita el tamaño del contexto.
  • MCP avanza hacia un mejor soporte nativo de caché (ttlMs, cacheScope en el release candidate del 2026-07-28). Planifica el uso de transporte HTTP Streamable, servidores sin estado y evals antes de considerar que el sistema está listo para producción.
  • Si ya conoces la infraestructura de sitios web preparada para agentes y los fundamentos de diseño de RAG, este artículo conecta ambos temas: cómo ofrecer el conocimiento público de tu app como una superficie de producto segura y económica para agentes.

Qué aprenderás aquí

  • Qué deberían entender los PMs e ingenieros por “datos públicos de una app”
  • Una arquitectura de referencia para MCP + RAG sobre un corpus público
  • Cómo establecer el límite de seguridad entre lecturas públicas y escrituras privadas
  • Decisiones de diseño de un servidor MCP: recursos frente a herramientas, autenticación, caché y tarjetas de servidor
  • Patrones de RAG que siguen siendo seguros, rápidos y económicos a escala
  • Un ejemplo concreto de asistente para documentación pública con fragmentos de código
  • Una lista de verificación para producción que puedes usar antes del lanzamiento

Estructura propuesta del artículo

Este artículo asume que quieres exponer el conocimiento del producto a agentes y usuarios externos sin abrir todo tu backend. Las siguientes secciones avanzan desde el enfoque de producto → arquitectura → seguridad → MCP → RAG → ejemplo → lista de verificación. Si tu objetivo es únicamente un RAG interno para empleados, omite las secciones sobre la allowlist pública y conserva las recomendaciones de producción para MCP/RAG.

La pregunta de producto: ¿qué debería ser público?

Antes de MCP o RAG, responde una pregunta de producto:

¿Qué partes de los datos de nuestra app ayudan a usuarios y agentes a tomar mejores decisiones cuando se comparten abiertamente?

Buenos candidatos para ser públicos:

  • documentación del producto, referencias de API, guías de SDK
  • páginas de precios, límites de planes, matrices de funcionalidades
  • registros públicos de cambios, notas de versión, páginas de estado
  • catálogos abiertos: integraciones, plantillas, conjuntos de datos públicos, publicaciones de marketplace
  • artículos de soporte marcados para consumo público
  • APIs de lectura con alcance limitado: “buscar documentación pública”, “obtener límites de planes”, “listar integraciones públicas”

Malos candidatos para ser públicos:

  • registros de clientes, historial de facturación, tickets de soporte con PII
  • runbooks internos, notas de incidentes, directorios de empleados
  • exportaciones sin procesar de bases de datos “porque los embeddings necesitan texto”
  • herramientas de administración, APIs de escritura o cualquier cosa que modifique el estado sin autenticación robusta

Usa un filtro sencillo:

PreguntaPúblicoPrivado
¿Publicaríamos esto en nuestro sitio de marketing?Por lo general, sí—
¿Contiene datos específicos de un usuario o tenant?—Sí
¿Podría un agente interpretar esto como permiso para actuar?Rediseñar la superficie—
¿Queda desactualizado en cuestión de horas?Necesita un pipeline de actualización—
¿Los equipos de ventas o legal ya aprobaron que se comparta externamente?Buena señalRevisar

Mi opinión editorial: la mayoría de los equipos falla aquí al indexar todo lo que se puede buscar en lugar de definir un corpus público con responsables, TTLs y reglas de revisión.

Tres capas, un corpus público

Piensa en tres capas que comparten una única fuente de referencia incluida en una allowlist:

Layer 1: Discoverable Content
  llms.txt, markdown pages, sitemap, /openapi or API catalog
  -> passive reading for crawlers and agents

Layer 2: MCP Server
  resources (read structured public data)
  tools (bounded queries: search_docs, get_pricing, list_integrations)
  -> active capability discovery and tool calls

Layer 3: RAG Service
  hybrid retrieval + rerank + citations over the same public index
  -> semantic answers with evidence and refusal behavior

¿Por qué tres capas en lugar de una?

  • Contenido estático es la superficie más económica. Los agentes pueden leerlo sin que tu infraestructura ejecute un modelo.
  • MCP proporciona a los clientes host una forma estándar de descubrir e invocar capacidades. La especificación de MCP define servidores que exponen recursos, prompts y herramientas mediante JSON-RPC.
  • RAG ayuda cuando los usuarios hacen preguntas en lenguaje natural que abarcan muchas páginas, necesitan ordenar resultados por relevancia o requieren respuestas sintetizadas con citas.

El error es construir una sola capa. La documentación por sí sola es difícil de consultar. RAG por sí solo es difícil de descubrir y auditar. MCP por sí solo no reemplaza la calidad de búsqueda necesaria para preguntas imprecisas.

                    +------------------+
                    |  Public corpus   |
                    |  (allowlisted)   |
                    +--------+---------+
                             |
           +-----------------+-----------------+
           |                 |                 |
           v                 v                 v
    +-------------+   +-------------+   +-------------+
    | Static web  |   | MCP server  |   | RAG index   |
    | llms.txt    |   | resources   |   | chunks +    |
    | *.md pages  |   | tools       |   | metadata    |
    +------+------+   +------+------+   +------+------+
           |                 |                 |
           v                 v                 v
    Crawlers /          Agent hosts /       Your app chat /
    research agents     Claude, Cursor      support bot

Para conocer los fundamentos de descubrimiento, consulta Infraestructura preparada para agentes. Este artículo se centra en los datos de la app una vez que aceptas que los agentes leerán e invocarán tu producto.

Arquitectura de referencia

Esta es una configuración inicial orientada a producción para un producto SaaS que expone conocimiento público:

Public sources                Ingestion                     Serving
-------------                 --------                      -------

/docs/*.md          ----->    Normalize + frontmatter  ---> Static CDN
/api/openapi.yaml            Extract stable IDs            llms.txt
/pricing.json                Chunk + hash                  markdown routes
/changelog/*.md              Embed changed chunks only     MCP HTTP server
/public/catalog.json         Metadata: product, version    RAG API
                             Freshness timestamps          Search UI

                             +-------- cache tier ---------+
                             | embedding cache             |
                             | retrieval-set cache         |
                             | semantic Q->docs cache      |
                             | provider prompt cache       |
                             +-----------------------------+

                             +-------- safety tier --------+
                             | public allowlist only       |
                             | auth on write tools         |
                             | scope checks per tool       |
                             | evals + refusal tests       |
                             +-----------------------------+

Reglas de diseño:

  1. Una allowlist, muchas superficies. No mantengas por separado la “documentación del sitio web” y la “documentación para RAG” si van a terminar desincronizadas.
  2. Procesamiento detrás de un gateway. El navegador, el host de agentes y el cliente MCP acceden a tu capa de API, no directamente a tu base de datos.
  3. Separa las herramientas MCP de lectura y escritura. Las lecturas públicas pueden no requerir autenticación o tener límites de tasa poco restrictivos. Las escrituras requieren OAuth y scopes por herramienta.
  4. Mide toda la cadena. El recall de recuperación y la calidad de las citas importan tanto como la fluidez de las respuestas. Consulta Apps RAG en la práctica.

Seguridad: público por diseño, no por accidente

“Público” es una propiedad de seguridad. Trátalo como tal.

1. Crea una allowlist pública, no una denylist privada

La ingesta debe leer de rutas o tablas explícitas:

/content/public/**
/openapi/public.yaml
/pricing/plans.public.json

Nunca apuntes el indexador a réplicas de la base de datos de producción, a menos que las filas se filtren previamente mediante un proceso de exportación pública.

2. Separa los recursos y las herramientas MCP según su riesgo

SuperficieAdecuada paraAutenticación
resources/public/*registros de cambios, páginas de políticas, catálogos estáticosa menudo ninguna
tools/search_public_docsbúsqueda de alcance limitado sobre el índice públicolímite de tasa opcional
tools/get_plan_limitsdatos estructurados del productoopcional
tools/create_support_ticketescritura de datos de usuarioOAuth + scopes

El tutorial de autorización de MCP es explícito: la autorización protege recursos y operaciones sensibles. La autorización es opcional en MCP, pero si tu servidor maneja datos de usuarios o acciones administrativas, usa OAuth 2.1 con HTTPS en producción.

Para endpoints protegidos, los servidores MCP deberían implementar OAuth 2.0 Protected Resource Metadata en /.well-known/oauth-protected-resource, y los clientes descubren el servidor de autorización a partir de ese documento. Aplica los scopes a nivel de herramienta, no solo en la entrada del servidor. Consulta Cómo construir un servidor MCP con inicio de sesión de Auth0 en Go y OpenFGA para permisos granulares para profundizar en el modelado de autorización.

3. Filtra antes de la recuperación, no después de la generación

Si un chunk no debe ser público, no debe convertirse en un embedding.

Bad:  retrieve top-k -> prompt "ignore private data"
Good: metadata.is_public = true filter -> retrieve -> generate

Para espacios de trabajo mixtos, usa autorización a nivel de objeto en la ruta de recuperación. Las verificaciones con OpenFGA o un equivalente deben ocurrir antes de que los chunks entren en el contexto del modelo.

4. Agrega requisitos para rechazar respuestas y proporcionar procedencia

Un RAG público debería:

  • citar IDs y URLs estables de las fuentes
  • rechazar la respuesta cuando falte evidencia
  • dar preferencia a la documentación exacta para datos de precios, límites y cumplimiento
  • identificar claramente la síntesis cuando combine varias páginas

Benchmarks como CRAG y RGB siguen mostrando que un RAG básico mejora las respuestas, pero todavía falla ante el ruido, los datos desactualizados y las situaciones en las que debería decir “no lo sé”. Crea evals para esos casos antes del lanzamiento.

5. Limita la tasa y monitorea patrones de exfiltración

Los endpoints públicos serán objeto de scraping. Planifica:

  • límites de tasa por IP y por token
  • alertas de anomalías ante consultas de enumeración amplias
  • registro de llamadas a herramientas sin registrar secretos ni cuerpos de JWT
  • claves de caché que no filtren identificadores de tenants en entradas de caché pública compartida

Construcción del corpus público

Un RAG de producción comienza con disciplina en la ingesta.

IDs y metadatos estables

Cada documento público debería incluir:

id: docs/api/authentication
source_url: https://example.com/docs/api/authentication.md
product: platform
visibility: public
version: 2026-06-01
updated_at: 2026-06-28T10:00:00Z
content_hash: sha256:...

Los IDs estables hacen posibles las citas, los conjuntos de datos para evals y la invalidación de caché.

Divide en chunks sin perder la estructura

No elimines la estructura de tablas, bloques de código ni jerarquías de políticas. Prefiere:

  • chunks padre/hijo para documentos largos
  • divisiones que respeten las secciones
  • metadatos para la ruta de encabezados (h1 > h2 > h3)
  • chunks separados para tablas de precios y límites

Esto sigue las recomendaciones de Apps RAG en la práctica: conserva la estructura del conocimiento sobre el que realmente preguntan los usuarios.

Vuelve a generar embeddings solo cuando cambie el contenido

Calcula un hash de cada chunk durante la ingesta. Si content_hash no cambió, omite las llamadas para generar embeddings. A escala, esta es una de las mejoras más económicas del pipeline.

Niveles de vigencia

No todos los datos públicos se desactualizan al mismo ritmo:

NivelEjemplosEstrategia de actualización
Estáticoguías, conceptosreconstruir al publicar
Semidinámicoprecios, límitessincronización programada + revisión manual
Dinámicoestado, notas de versiónwebhook o caché con TTL corto

Expón la vigencia en los metadatos de los recursos MCP y en las respuestas de RAG cuando la respuesta dependa de datos sensibles al tiempo.

Diseño de un servidor MCP para producción

MCP es el contrato entre tu app y hosts de agentes como Claude, Cursor, ChatGPT y VS Code.

Recursos frente a herramientas

Usa recursos cuando el cliente deba leer contexto público estructurado:

  • public://docs/getting-started
  • public://pricing/plans
  • public://changelog/2026-06-30

Usa herramientas cuando el agente deba invocar una operación de alcance limitado:

  • search_public_docs(query, product, limit)
  • get_integration(slug)
  • list_public_templates(category)

Mantén acotadas las entradas de las herramientas. Prefiere salidas estructuradas con IDs de fuentes en lugar de prosa libre.

Tarjetas de servidor y descubrimiento

Publica una tarjeta de servidor MCP legible por máquina y enlázala desde llms.txt o el pie de página de tu documentación. Hoy pocos productos hacen esto, y precisamente por eso quienes lo adopten temprano pueden ganar distribución en hosts de agentes. Los patrones de descubrimiento se explican en Infraestructura preparada para agentes.

Transporte y despliegue

Para servidores públicos remotos:

  • prefiere el transporte HTTP Streamable en producción
  • mantén el servidor MCP sin estado; pasa IDs explícitos en los argumentos de las herramientas
  • colócalo detrás de un proxy inverso con TLS, verificaciones de estado y tiempos de espera para las solicitudes
  • separa el servidor de autorización OAuth del servidor de recursos MCP

El release candidate de la especificación de MCP del 2026-07-28, cerrado el 21 de mayo de 2026, orienta el protocolo principal hacia HTTP sin estado y agrega indicaciones de caché estandarizadas (ttlMs, cacheScope) en los resultados de listado y lectura. La publicación final está prevista para el 28 de julio de 2026. Si empiezas ahora, diseña handlers sin estado y encabezados de caché explícitos para no tener que reconstruir cuando los clientes adopten la nueva versión.

Ejemplo: esquema mínimo de una herramienta MCP pública

{
  "name": "search_public_docs",
  "description": "Search publicly available product documentation. Returns snippets and source URLs only.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "minLength": 2, "maxLength": 200 },
      "product": { "type": "string", "enum": ["platform", "sdk", "cli"] },
      "limit": { "type": "integer", "minimum": 1, "maximum": 5, "default": 3 }
    },
    "required": ["query"]
  }
}

La implementación debería llamar a tu servicio de recuperación RAG o a tu índice de búsqueda, no ejecutar un LLM dentro del handler de la herramienta en cada llamada.

Capa RAG: segura, optimizada, con caché y económica

RAG sobre datos públicos sigue necesitando ingeniería para producción.

Pipeline de recuperación

Una configuración inicial sólida para conocimiento público del producto:

User question
     |
     v
Query rewrite (optional, small model)
     |
     v
Hybrid retrieval: BM25 + vector + metadata filters
     |
     v
Rerank top 20 -> keep top 3-5
     |
     v
Answer with citations + freshness note
     |
     v
Post-checks: grounding, policy, max tokens

Mantén pequeño el contexto. Muchos equipos recuperan diez chunks “por seguridad” y pagan por el ruido. Para documentación pública, entre tres y cinco buenos chunks suelen superar a diez mediocres.

Usa caché en cuatro niveles

Piensa más allá de la caché de prompts del proveedor:

L1  CDN / HTTP cache          static docs, llms.txt, MCP resource bodies
L2  Embedding cache           query/text -> vector
L3  Retrieval-set cache       query embedding -> chunk IDs + scores
L4  Semantic answer cache     similar question -> prior grounded answer

La caché de prompts del proveedor reduce el costo de repetir prompts de sistema largos y contexto recuperado estable en las APIs que la admiten. La caché semántica reduce las llamadas completas al LLM cuando las preguntas se repiten con distintas formulaciones. GPTCache es un patrón de referencia de código abierto para caché semántica de LLM; en producción, muchos equipos usan Redis, pgvector o su vector store actual para buscar por similitud.

Una nota práctica basada en implementaciones reales: guarda en caché resultados de recuperación o paquetes de respuestas fundamentadas (respuesta + IDs de fuentes), no solo el texto sin procesar del modelo, si usas una temperatura distinta de cero y quieres citas consistentes.

Define los umbrales de similitud de forma deliberada. Los asistentes de documentación pública suelen usar una similitud coseno de alrededor de 0.90–0.94 para aciertos de caché semántica, pero valídala con tus propios registros de consultas. Los umbrales más bajos ahorran dinero y aumentan el riesgo de respuestas desactualizadas o incorrectas.

Controles de costos que realmente se implementan

ControlQué ahorraConsideración
Documentación pública estáticaelimina las llamadas al LLM para muchas lecturassigue necesitando disciplina de actualización
Caché de conjuntos de recuperaciónembeddings, búsqueda vectorial, rerankerinvalidar cuando cambie el corpus
Caché de promptstokens de entrada repetidosagrupar primero el prefijo estable
Enrutamiento a modelos pequeñoscosto de generación en consultas sencillasnecesita verificaciones de paridad con evals
Límites de tokenscosto de salida y contextopuede reducir la integridad de la respuesta
Indexación por lotesgasto en embeddings durante las reconstruccionesno sirve para consultas en línea

Mi opinión práctica: los equipos que solo optimizan la elección del modelo sin guardar en caché la ruta de recuperación suelen dejar pasar la mitad del ahorro posible.

Evals antes de declarar que está “listo para producción”

Conjunto mínimo de evals para un RAG público:

  • 50–100 preguntas reales de usuarios
  • 20 casos negativos en los que debe rechazar la respuesta
  • 20 casos sensibles a la vigencia de los datos (precios, límites, deprecaciones)
  • métricas por componente: recall de recuperación@k, exactitud de las citas, fundamentación, latencia, costo por respuesta

Si expones el mismo corpus mediante herramientas MCP, agrega pruebas a nivel de herramienta:

  • validación del esquema de la herramienta
  • aplicación de scopes para herramientas protegidas
  • las herramientas de búsqueda deterministas devuelven los mismos IDs para la misma consulta
  • comportamiento ante límites de tasa y tiempos de espera

Ejemplo: asistente de documentación pública del producto

Esta es una estructura compacta de extremo a extremo que usa contenido estático al estilo de Astro junto con una ruta de servidor MCP/RAG.

1. Publica el corpus público

content/public/
  docs/
    getting-started.md
    authentication.md
  pricing/plans.json
  changelog/2026-06-30.md
public/
  llms.txt
  openapi/public-api.yaml

Tu sitio estático sirve markdown y llms.txt. El proceso de ingesta replica los mismos archivos en el índice vectorial.

2. Realiza la ingesta con hashes

# ingestion/public_index.py
import hashlib
from dataclasses import dataclass

@dataclass
class PublicChunk:
    id: str
    text: str
    source_url: str
    metadata: dict
    content_hash: str

def hash_text(text: str) -> str:
    return hashlib.sha256(text.encode("utf-8")).hexdigest()

def upsert_chunk(store, chunk: PublicChunk) -> None:
    existing = store.get_hash(chunk.id)
    if existing == chunk.content_hash:
        return  # skip re-embed
    vector = embed(chunk.text)
    store.save(chunk, vector)

3. Expón una búsqueda MCP que reutilice la recuperación

# mcp/public_server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Public Docs")

@mcp.tool()
def search_public_docs(query: str, product: str = "platform", limit: int = 3):
    results = retrieval.search(
        query=query,
        filters={"visibility": "public", "product": product},
        limit=min(limit, 5),
    )
    return {
        "results": [
            {
                "id": r.id,
                "title": r.title,
                "url": r.source_url,
                "snippet": r.snippet,
                "updated_at": r.updated_at,
            }
            for r in results
        ]
    }

4. Ruta de respuesta RAG con caché de conjuntos de recuperación

# rag/answer.py
def answer_public_question(question: str) -> dict:
    cache_key = semantic_key(question)
    cached = retrieval_cache.get(cache_key)
    if cached:
        chunks = cached
    else:
        chunks = retrieval.search(
            query=question,
            filters={"visibility": "public"},
            limit=4,
        )
        retrieval_cache.set(cache_key, chunks, ttl_seconds=900)

    if not chunks:
        return {"answer": "I could not find public documentation for that.", "sources": []}

    response = llm.generate(
        system=PUBLIC_DOCS_SYSTEM_PROMPT,
        context=format_chunks(chunks),
        question=question,
        max_output_tokens=300,
    )
    return {
        "answer": response.text,
        "sources": [{"id": c.id, "url": c.source_url} for c in chunks],
    }

5. Flujo de la solicitud

Agent host
   |
   |-- reads llms.txt + docs/*.md (free, cacheable)
   |
   |-- calls MCP tool search_public_docs
   |       -> retrieval-set cache
   |       -> hybrid search
   |
   '-- asks your RAG API for a synthesized answer
           -> retrieval-set cache
           -> rerank
           -> small/large model route
           -> citations

Esto mantiene un único índice público detrás de MCP y RAG, mientras permite que los agentes sencillos usen solo documentación estática o herramientas.

Lista de verificación para producción

Úsala antes de declarar que el sistema está listo para producción.

Producto / gobernanza de datos

  • Corpus público definido con responsables identificados
  • Revisión de legal y ventas para contenido sobre precios, cumplimiento y socios
  • Niveles de vigencia documentados
  • Ejemplos de lo que “no es público” documentados para soporte e ingeniería

Seguridad

  • Allowlist pública aplicada en la ingesta y la recuperación
  • OAuth 2.1 en herramientas protegidas, HTTPS en todas partes en producción
  • Scopes aplicados a nivel de herramienta
  • Sin secretos, tokens ni URLs privadas en logs, prompts o cachés
  • Límites de tasa y monitoreo de abuso habilitados

MCP

  • Recursos y herramientas separados según su riesgo
  • Tarjeta de servidor publicada y enlazada desde la documentación
  • Salidas estructuradas de herramientas con IDs estables
  • Verificaciones de estado y tiempos de espera configurados
  • Encabezados de caché o política de ttlMs documentados para endpoints de listado y lectura

RAG

  • Recuperación híbrida + filtros de metadatos
  • Hashes de chunks para evitar volver a generar embeddings innecesariamente
  • Caché de conjuntos de recuperación y umbrales de caché semántica validados
  • Caché de prompts del proveedor habilitada donde se admita
  • El conjunto de evals cubre el rechazo de respuestas, la vigencia de los datos y la exactitud de las citas
  • Costo por respuesta y latencia p95 monitoreados

Preparación operativa

  • Runbook de reindexación para publicaciones de documentación
  • Invalidación de caché vinculada a la versión del corpus
  • Dashboards para tasa de aciertos, tasa de errores, gasto y recall de recuperación
  • Playbooks de incidentes para respuestas con precios o políticas desactualizados

Qué no debes prometer de más

Una perspectiva equilibrada es importante para PMs e ingenieros:

  • MCP público más RAG no reemplaza las APIs de producto autenticadas para el estado específico de cada cliente.
  • La caché semántica reduce costos a cambio de riesgo de desactualización; ajusta los umbrales y TTLs de forma explícita.
  • El soporte de los hosts MCP varía según el cliente, el transporte y el flujo de autenticación. Prueba con los hosts que tus usuarios realmente usan.
  • Al 30 de junio de 2026, los cambios de MCP del 2026-07-28 siguen en proceso de validación del release candidate. Construye servidores sin estado desde ahora, pero fija las pruebas de compatibilidad a la versión de la especificación que tengas como objetivo.

Fuentes