MCP RAG Server

Un servidor ligero en Python para Generación Aumentada por Recuperación (RAG) utilizando AWS Lambda. Recupera conocimiento de fuentes de datos externas como arXiv y PubMed.

Documentación

Implementación de una Aplicación MCP

MCP (Model Context Protocol) se está expandiendo rápidamente como una interfaz clave para que las aplicaciones de IA generativa utilicen datos externos. Comenzó como un proyecto de código abierto de Anthropic en noviembre de 2024, y actualmente cuenta con soporte no solo de Cursor sino también de OpenAI. Aquí se explica cómo una aplicación creada con LangGraph puede utilizar MCP mediante MCP with LangChain. El RAG implementado aquí se basa en Knowledge Base, el servicio RAG totalmente administrado de Amazon, por lo que tareas como la extracción de texto de documentos, la sincronización y el chunking se pueden realizar fácilmente, y también se pueden analizar imágenes/tablas mediante multimodalidad. Aquí se configuró una API usando AWS Lambda para que el servidor MCP pueda acceder fácilmente al RAG.

La siguiente arquitectura muestra la construcción de un agente que incluye MCP en el entorno AWS. El agente utiliza la estructura de servidor/cliente MCP para aprovechar fuentes de datos externas. El cliente MCP se comunica con el servidor MCP mediante stdio/SSE basado en el protocolo JSON-RPC. Al usar stdio, el servidor MCP se compone de código como Python o Java, y cuando llega una solicitud del cliente, se encarga de recopilar o entregar datos utilizando RAG o Internet. En el caso de SSE, el cliente y el servidor MCP se comunican por IP. Aquí se utiliza Streamlit para construir la interfaz de usuario de la aplicación, y los usuarios acceden a la aplicación a través del navegador mediante HTTPS usando ALB - CloudFront. Además, aquí se explica el desarrollo de una aplicación basada en MCP utilizando LangGraph, que es ventajoso para la personalización.

Uso de MCP

Conceptos básicos de MCP

Los usuarios pueden conectarse a servidores MCP no solo a través de herramientas de IA instaladas en su computadora, como Claude Desktop o Cursor, sino también a través de aplicaciones desarrolladas principalmente en forma de agentes. El servidor MCP proporciona sus capacidades al cliente MCP y ejecuta las solicitudes del cliente. El servidor MCP puede consultar archivos o bases de datos locales de la computadora, así como utilizar API de servidores externos en Internet para obtener la información necesaria. El cliente MCP se conecta al servidor mediante el protocolo JSON-RPC 2.0, eligiendo stdio o SSE (Server-Sent Events), para transmitir las solicitudes del host al MCP y recibir las respuestas.

La definición y el funcionamiento de los elementos principales de MCP son los siguientes:

  • MCP Hosts: Programas/herramientas de IA que acceden a datos a través del protocolo MCP, como Claude Desktop, Cursor y aplicaciones de agente de usuario.
  • MCP Clients: Clientes que se conectan 1:1 con el servidor MCP, pudiendo conectarse mediante stdio o SSE.
  • MCP Servers: Programas ligeros que informan al cliente sobre las capacidades de las herramientas a través de MCP estandarizado; pueden consultar archivos o bases de datos locales y obtener información mediante API externas.
  • Local data sources: Bases de datos y datos locales a los que el servidor MCP puede acceder.
  • Remote services: Sistemas externos accesibles mediante API.

El uso de MCP ofrece las siguientes ventajas:

  • Permite acceder a diversas fuentes de datos de manera estandarizada.
  • Se pueden añadir nuevas funciones mediante actualizaciones del servidor MCP sin cambiar el código de la aplicación.
  • Facilita el soporte y la expansión de IA en toda la organización.

MCP Server Components incluye los siguientes elementos:

  • Tools (controlados por el modelo): Funciones (herramientas) que el LLM puede invocar para realizar tareas específicas; ejecutan acciones concretas, como una API.
tools = await session.list_tools()
  • Resources (controlados por la aplicación): Fuentes de datos a las que la aplicación de IA generativa puede acceder. Permiten obtener datos sin cálculos complejos ni efectos secundarios.
resources = await session.list_resources()
  • Prompts (controlados por el usuario): Plantillas predefinidas que se utilizan al emplear herramientas o recursos; se pueden seleccionar antes de la inferencia.
prompts = await session.list_prompts()

Arquitectura de operación

En la interfaz de Streamlit (app.py), al seleccionar el tipo de conversación, el tipo de agente y el servidor MCP, chat.py enruta según el modo. El modo Agente admite tres implementaciones: LangGraph, Strands y Claude Agent SDK. La configuración del servidor MCP se carga en mcp_config.py mediante transporte stdio / streamable HTTP.

flowchart TB
  subgraph UI["Streamlit (app.py)"]
    MODE["대화 형태 / Agent 타입"]
    MCPUI["MCP 서버 선택"]
  end

  subgraph Router["chat.py"]
    RAG[run_rag_with_knowledge_base]
    LG[run_langgraph_agent]
    ST[run_strands_agent]
    CA[run_claude_agent]
  end

  subgraph LLM["Amazon Bedrock"]
    BR[Bedrock Runtime]
    KB[Knowledge Base]
  end

  subgraph Agents["Agent 구현"]
    LGA["LangGraph\nMultiServerMCPClient + built-in tools"]
    STA["Strands\nMCPClientManager + strands_tools"]
    CLA["Claude SDK\nClaudeSDKClient + MCP"]
  end

  subgraph MCPServers["MCP Servers (mcp_config.py)"]
    MCP["knowledge base · tavily · aws document · korea_weather · ..."]
  end

  subgraph Storage["Artifacts / S3"]
    ART[artifacts/]
    S3[(S3)]
  end

  MODE --> RAG
  MODE --> LG
  MODE --> ST
  MODE --> CA
  MCPUI --> MCPServers

  RAG --> KB --> BR

  LG --> LGA --> BR
  ST --> STA --> BR
  CA --> CLA --> BR

  LGA --> MCPServers
  STA --> MCPServers
  CLA --> MCPServers

  LGA --> ART
  STA --> ART
  LGA --> S3
  STA --> S3
ModoMóduloDescripción
Conversación cotidianachat.general_conversationHistorial de conversación + streaming de Bedrock Runtime invoke_model_with_response_stream
RAGchat.run_rag_with_knowledge_baseBúsqueda en Bedrock Knowledge Base (retrieve) y generación de respuestas con Bedrock Runtime
Agente / Agente (Chat) — langgraphchat.run_langgraph_agentLangGraph StateGraph + LangChain MultiServerMCPClient + herramientas integradas
Agente / Agente (Chat) — strandschat.run_strands_agentStrands SDK + strands_tools + MCPClientManager + herramientas integradas
Agente / Agente (Chat) — claudeclaude_agent.run_claude_agentClaude Agent SDK (ClaudeSDKClient) + MCP (backend Bedrock)
Análisis de imágeneschat.summarize_image / chat.get_image_summarizationAnálisis multimodal de ChatBedrock (imagen + texto)
Traducirchat.translate_textTraducción coreano↔inglés
Revisión gramaticalchat.check_grammerRevisión y sugerencias de corrección gramatical en coreano e inglés

El modo Agente (Chat) utiliza la misma implementación de agente que el modo Agente, pero mantiene el historial de conversación mediante history_mode=Enable. Los servidores MCP se pueden seleccionar múltiples en la barra lateral, y la configuración de stdio o streamable HTTP se fusiona mediante mcp_config.load_selected_config().

Adaptador MCP de LangChain

LangChain MCP Adapter es un envoltorio ligero que permite usar MCP con agentes de LangGraph, y es un proyecto de código abierto con licencia MIT. La función principal del adaptador MCP es definir herramientas para el servidor MCP, consultar la información de las herramientas desde el cliente MCP y permitir que se utilicen como nodo de herramientas de LangGraph.

Preparación

Instale MCP y LangChain MCP Adapter de la siguiente manera.

pip install mcp langchain-mcp-adapters

Servidor MCP

El servidor MCP para la búsqueda RAG se puede definir de la siguiente manera. Al especificar el transporte del servidor como "stdio", el cliente puede ejecutar directamente el código Python del servidor sin necesidad de mantenerlo en ejecución continua, lo cual es conveniente.

from mcp.server.fastmcp import FastMCP 

mcp = FastMCP(
    name = "retrieve"
) 

@mcp.tool()
def rag_search(keyword: str) -> str:
    "search keyword"

    return retrieve(keyword)

if __name__ =="__main__":
    mcp.run(transport="stdio")

Cuando llega una solicitud, el servidor realiza la búsqueda RAG con retrieve_knowledge_base().

bedrock_agent_runtime_client = boto3.client("bedrock-agent-runtime", region_name=bedrock_region)

def retrieve(query):
    response = bedrock_agent_runtime_client.retrieve(
        retrievalQuery={"text": query},
        knowledgeBaseId=knowledge_base_id,
        retrievalConfiguration={
            "vectorSearchConfiguration": {"numberOfResults": number_of_results},
        },
    )
    payload = json.load(output['Payload'])
    return payload['response'], []

En relación con Drug discovery, se admiten arXiv, ChEMBL, ClinicalTrials.gov y PubMed.

Cliente MCP

Si el cliente MCP solo ve un servidor MCP, se puede implementar usando stdio_client y StdioServerParameters como se muestra a continuación. La información del servidor MCP se puede leer desde config.json o usar la información ingresada por el usuario en Streamlit. load_mcp_server_parameters() lee mcp_json y construye StdioServerParameters.

from mcp import ClientSession, StdioServerParameters

def load_mcp_server_parameters():
    mcp_json = json.loads(mcp_config)
    mcpServers = mcp_json.get("mcpServers")

    command = ""
    args = []
    if mcpServers is not None:
        for server in mcpServers:
            config = mcpServers.get(server)
            if "command" in config:
                command = config["command"]
            if "args" in config:
                args = config["args"]
            break

    return StdioServerParameters(
        command=command,
        args=args
    )

Configure stdio_client con la información del servidor MCP como se muestra a continuación. En este punto, la información de las herramientas se obtiene con load_mcp_tools. En el agente, se vincula la información de las herramientas y se ejecuta la acción solicitada mediante ainvoke.

from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools

server_params = load_mcp_server_parameters()

client = MultiServerMCPClient(server_params)
tools = await client.get_tools()

app = buildAgent(tools)
config = {
    "recursion_limit": 50,
    "configurable": {"thread_id": user_id},
    "tools": tools,
    "system_prompt": None
}

inputs = {
    "messages": [HumanMessage(content=query)]
}

async for output in app.astream(inputs, config):
    for key, value in output.items():
        if isinstance(value, dict) and "messages" in value:
            final_output = value

if final_output and "messages" in final_output and len(final_output["messages"]) > 0:
    result = final_output["messages"][-1].content
else:
    result = "답변을 찾지 못하였습니다."

Aquí se utiliza un agente LangGraph de estilo ReAct como se muestra a continuación.

def call_model(state: State, config):
    system = (
        "당신의 이름은 서연이고, 질문에 친근한 방식으로 대답하도록 설계된 대화형 AI입니다."
        "상황에 맞는 구체적인 세부 정보를 충분히 제공합니다."
        "모르는 질문을 받으면 솔직히 모른다고 말합니다."
        "한국어로 답변하세요."
    )
    try:
        prompt = ChatPromptTemplate.from_messages(
            [
                ("system", system),
                MessagesPlaceholder(variable_name="messages"),
            ]
        )
        chain = prompt | model                
        response = chain.invoke(state["messages"])
    return {"messages": [response]}

def should_continue(state: State) -> Literal["continue", "end"]:
    messages = state["messages"]    
    last_message = messages[-1]
    if isinstance(last_message, AIMessage) and last_message.tool_calls:
        return "continue"        
    else:
        return "end"

def buildAgent(tools):
    tool_node = ToolNode(tools)

    workflow = StateGraph(State)

    workflow.add_node("agent", call_model)
    workflow.add_node("action", tool_node)
    workflow.add_edge(START, "agent")
    workflow.add_conditional_edges(
        "agent",
        should_continue,
        {
            "continue": "action",
            "end": END,
        },
    )
    workflow.add_edge("action", "agent")

    return workflow.compile()

El cliente MCP se ejecuta de la siguiente manera. Se utilizó asyncio para la ejecución asíncrona.

asyncio.run(mcp_agent(query, st))

Aquí se definió el agente para facilitar la personalización.

Uso de servidores MCP

Model Context Protocol servers también proporciona información sobre los siguientes servidores:

Puede buscar servidores MCP en Smithery y, si encuentra el servidor necesario, puede consultar la información del servidor MCP en formato JSON.

La información del servidor MCP para búsqueda de Google, verificada en Smithery - Google Search Server, es la siguiente. Requiere el ID del motor de búsqueda y la clave de API.

{
  "mcpServers": {
    "google-search-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "@smithery/cli@latest",
        "run",
        "@gradusnikov/google-search-mcp-server",
        "--config",
        "{\"googleCseId\":\"b5cd8c527fbd64b72\",\"googleApiKey\":\"AIzbSyDQlYpck8-9TbBSuxoew1luOGVB6unRPNk\"}"
      ]
    }
  }
}

Puede actualizar la información del servidor en formato JSON como se muestra a continuación. Aquí se utiliza la búsqueda definida en mcp-server.py.

{
  "mcpServers": {
    "search": {
      "command": "python",
      "args": [
        "application/mcp-server.py"
      ]
    }
  }
}

Análisis de costos de AWS

Como herramienta MCP, puede obtener y analizar la información de costos de AWS de la siguiente manera.

from datetime import datetime, timedelta
import pandas as pd

def get_cost_analysis(days: str=30):
    end_date = datetime.now()
    start_date = end_date - timedelta(days=days)    
    ce = boto3.client('ce')
    service_response = ce.get_cost_and_usage(
        TimePeriod={
            'Start': start_date.strftime('%Y-%m-%d'),
            'End': end_date.strftime('%Y-%m-%d')
        },
        Granularity='MONTHLY',
        Metrics=['UnblendedCost'],
        GroupBy=[{'Type': 'DIMENSION', 'Key': 'SERVICE'}]
    )        
    service_costs = pd.DataFrame([
        {
            'SERVICE': group['Keys'][0],
            'cost': float(group['Metrics']['UnblendedCost']['Amount'])
        }
        for group in service_response['ResultsByTime'][0]['Groups']
    ])
        
    # region cost
    region_response = ce.get_cost_and_usage(
        TimePeriod={
            'Start': start_date.strftime('%Y-%m-%d'),
            'End': end_date.strftime('%Y-%m-%d')
        },
        Granularity='MONTHLY',
        Metrics=['UnblendedCost'],
        GroupBy=[{'Type': 'DIMENSION', 'Key': 'REGION'}]
    )
    region_costs = pd.DataFrame([
        {
            'REGION': group['Keys'][0],
            'cost': float(group['Metrics']['UnblendedCost']['Amount'])
        }
        for group in region_response['ResultsByTime'][0]['Groups']
    ])
        
    # Daily Cost
    daily_response = ce.get_cost_and_usage(
        TimePeriod={
            'Start': start_date.strftime('%Y-%m-%d'),
            'End': end_date.strftime('%Y-%m-%d')
        },
        Granularity='DAILY',
        Metrics=['UnblendedCost'],
        GroupBy=[{'Type': 'DIMENSION', 'Key': 'SERVICE'}]
    )    
    daily_costs = []
    for time_period in daily_response['ResultsByTime']:
        date = time_period['TimePeriod']['Start']
        for group in time_period['Groups']:
            daily_costs.append({
                'date': date,
                'SERVICE': group['Keys'][0],
                'cost': float(group['Metrics']['UnblendedCost']['Amount'])
            })    
    daily_costs_df = pd.DataFrame(daily_costs)
        
    return {
        'service_costs': service_costs,
        'region_costs': region_costs,
        'daily_costs': daily_costs_df
    }

Para graficar los 3 resultados de costos anteriores, se requiere instalar los siguientes paquetes.

pip install -U kaleido

Generación de imágenes MCP

Registre una herramienta de generación de imágenes como en mcp_server_image_generation.py.

La configuración de MCP se establece de la siguiente manera. Consulte mcp_config.py.

{
    "mcpServers": {
        "imageGeneration": {
            "command": "python",
            "args": [
                "application/mcp_server_image_generation.py"
            ]
        }
    }
}

Luego, genere la imagen como en mcp_nova_canvas.py.

async def mcp_generate_image(ctx, prompt, negative_prompt, filename, width, height, quality, cfg_scale, seed, number_of_images):
    """Generate an image using Amazon Nova Canvas with text prompt."""
    
    response = await generate_image_with_text(
        prompt=prompt,
        negative_prompt=negative_prompt,
        filename=filename,
        width=width,
        height=height,
        quality=quality,
        cfg_scale=cfg_scale,
        seed=seed,
        number_of_images=number_of_images
    )

    return {
        "url": [f'{path}' for path in response.paths]
    } 

Los resultados obtenidos de image_generation de MCP se muestran de la siguiente manera. Consulte chat.py para más detalles.

def show_status_message(response, st):
    image_url = []
    for i, re in enumerate(response):
        logger.info(f"message[{i}]: {re}")
        if i==len(response)-1:
            break
        if isinstance(re, ToolMessage):
          tool_result = json.loads(re.content)
          logger.info(f"tool_result: {tool_result}")

          if "url" in tool_result:
              st.info(f"URL: {tool_result['url']}")

              urls = tool_result['url']
              for url in urls:
                  image_url.append(url)
                  st.image(url)
    return image_url

Diagrama AWS MCP

Con AWS Diagram MCP Server puede dibujar diagramas de AWS. Consulte mcp_config.py para más detalles.

La configuración de MCP utilizada es la siguiente.

{
    "mcpServers": {
        "awslabs.aws-diagram-mcp-server": {
            "command": "uvx",
            "args": ["awslabs.aws-diagram-mcp-server"],
            "env": {
                "FASTMCP_LOG_LEVEL": "ERROR"
            },
        }
    }
}

Para dibujar diagramas, instale graphviz siguiendo Graphviz. En Mac, use el siguiente comando.

brew install graphviz

Documentación de AWS MCP

Con AWS Documentation MCP Server puede consultar documentos de AWS. La configuración de MCP utilizada es la siguiente. Consulte mcp_config.py para más detalles.

{
    "mcpServers": {
        "awslabs.aws-documentation-mcp-server": {
            "command": "uvx",
            "args": ["awslabs.aws-documentation-mcp-server@latest"],
            "env": {
                "FASTMCP_LOG_LEVEL": "ERROR"
            }
        }
    }
}

Cómo verificar los modelos disponibles por región

La forma de verificar los modelos disponibles es la siguiente.

aws bedrock list-foundation-models --region=us-west-2 --by-provider anthropic --query "modelSummaries[*].modelId"

Recorte de mensajes

El agente de LangGraph (application/langgraph_agent.py de call_model) conserva solo los últimos N turnos basados en HumanMessage justo antes de la llamada al LLM. El messages del estado de LangGraph se mantiene en el checkpointer, y solo se recortan los mensajes que se pasan al modelo. Se aplica igualmente a history_mode=Enable/Disable.

Valor predeterminado: MAX_CONTEXT_TURNS = 5 (intención de "últimos 5 turnos", igual que SimpleMemory(k=5) del chat general)

Cambio de configuración:

La constante y la función de recorte se definen en langgraph_agent.py.

# application/langgraph_agent.py
MAX_CONTEXT_TURNS = 5


def trim_messages_by_human_turns(messages: list, max_turns: int) -> list:
    """Keep messages from the last N HumanMessage turns (inclusive)."""
    if max_turns <= 0 or not messages:
        return messages

    human_indices = [i for i, msg in enumerate(messages) if isinstance(msg, HumanMessage)]
    if len(human_indices) <= max_turns:
        return messages

    return messages[human_indices[-max_turns]:]

En call_model, se aplica el recorte después de normalizar el contenido de ToolMessage.

# application/langgraph_agent.py — call_model() 내부
        max_turns = (
            config.get("configurable", {}).get("max_turns")
            or config.get("max_turns")
            or MAX_CONTEXT_TURNS
        )
        trimmed = trim_messages_by_human_turns(messages, max_turns)
        if len(trimmed) < len(messages):
            logger.info(
                f"trimmed messages from {len(messages)} to {len(trimmed)} "
                f"(max_turns={max_turns})"
            )
            messages = trimmed

        prompt = ChatPromptTemplate.from_messages(
            [
                ("system", system),
                MessagesPlaceholder(variable_name="messages"),
            ]
        )
        chain = prompt | model
        async for chunk in chain.astream({"messages": messages}):
            ...

El config del agente se crea en create_agent() de chat.py, y se pasa max_turns independientemente de history_mode.

# application/chat.py — create_agent()
    if history_mode == "Enable":
        app = langgraph_agent.buildChatAgentWithHistory(tools)
        config = {
            "recursion_limit": 50,
            "configurable": {
                "thread_id": user_id,
                "tools": tools,
                "system_prompt": None,
            },
            "max_turns": langgraph_agent.MAX_CONTEXT_TURNS,
        }
    else:
        app = langgraph_agent.buildChatAgent(tools)
        config = {
            "recursion_limit": 50,
            "configurable": {
                "thread_id": user_id,
                "tools": tools,
                "system_prompt": None,
            },
            "max_turns": langgraph_agent.MAX_CONTEXT_TURNS,
        }

Significado de max_turns=5

  • Mantiene 5 HumanMessage de usuario y todos los mensajes posteriores de cada turno
  • 1 turno = 1 HumanMessage + los AIMessage, ToolMessage y todo el bucle de retroalimentación de herramientas posteriores
  • Aunque se llame a las herramientas varias veces, si es la misma pregunta del usuario, cuenta como 1 turno

Ejemplo (incluye uso de herramientas)

Human(Q1) → AI(tool_calls) → ToolMessage → AI(A1)
Human(Q2) → AI(A2)
Human(Q3) → AI(tool_calls) → ToolMessage → AI(A3)

Si es max_turns=2, se mantiene desde Q2:

Human(Q2) → AI(A2) → Human(Q3) → AI(tool_calls) → ToolMessage → AI(A3)

Diferencia con el recorte por cantidad de mensajes

MétodoCuando es N=5
Anterior (cantidad de mensajes)Solo se mantienen 5 objetos de mensaje → el número de turnos de usuario es irregular debido al bucle de herramientas
Actual (turnos de HumanMessage)5 preguntas de usuario + todas las respuestas de IA/Herramientas de cada turno

Relación con el Checkpointer

  • Cuando es history_mode=Enable, el checkpointer MemorySaver almacena todo el historial de conversación.
  • El recorte es para la gestión de la ventana de contexto del LLM y no elimina el historial guardado.
  • Puede verificar si se aplicó el recorte mediante trimmed messages from X to Y (max_turns=5) en CloudWatch (/ecs/...) o en los registros de la aplicación.

Implementación

Implementación en EC2

Conéctese a EC2 en la consola de AWS y seleccione Launch an instance. Después de seleccionar [Launch instance], ingrese un nombre adecuado (por ejemplo: es). En key pair, seleccione "Proceed without key pair" y continúe.

ec2이름입력

Cuando la instancia esté lista, seleccione [Connect] - [EC2 Instance Connect] para conectarse como se muestra a continuación.

image

Luego, instale python, pip, git y boto3 como se muestra a continuación.

sudo yum install python3 python3-pip git docker -y
pip install boto3

En el caso del Workshop, copie las credenciales en el formato que se muestra a continuación e ingréselas en la terminal de EC2.

credential

Obtenga el código fuente de git como se muestra a continuación.

git clone https://github.com/kyopark2014/es-us-project

Inicie la instalación con installer.py como se muestra a continuación.

cd es-us-project && python3 installer.py

Las credenciales necesarias para la implementación de la API se gestionan como secretos. Por lo tanto, se requiere ingresar las credenciales durante la instalación; prepare las credenciales con anticipación utilizando los siguientes métodos.

  • Búsqueda general en Internet: Acceda a Tavily Search, regístrese y emita la clave de API. Esta comienza con tvly-.
  • Búsqueda del clima: Acceda a openweathermap y emita la clave de API. En este caso, seleccione el plan de precios "Free".

Cuando la instalación esté completa, conéctese a CloudFront como se muestra a continuación para verificar el funcionamiento.

cloudfront_address

Cuando la infraestructura ya no sea necesaria, elimínela con uninstaller.py.

python uninstaller.py

Actualización de la aplicación implementada

Conéctese a EC2 en la consola de AWS, seleccione Launch an instance y elija el ID de instancia con el nombre "app-for-es-us" como se muestra a continuación.

image

Seleccione [Connect] y luego elija Session Manager para conectarse.

image

Luego, actualice como se muestra a continuación y verifique nuevamente en el navegador.

cd ~/es-us-project/ && sudo ./update.sh

Verificación de registros de ejecución

En EC2 console, seleccione el ID de instancia con el nombre "app-for-es-us" y conéctese mediante Session Manager de EC2.

Primero, verifique el ID del contenedor Docker actual como se muestra a continuación.

sudo docker ps

Luego, verifique los registros usando el ID del contenedor como se muestra a continuación.

sudo docker logs [container ID]

El resultado real de la ejecución es el siguiente.

Ejecución local

Para aprovechar bien el entorno de AWS, debe instalar AWS CLI. Al implementar en EC2, no se requiere instalación adicional. Para instalación local, consulte el siguiente comando.

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" 
unzip awscliv2.zip
sudo ./aws/install

Registre las credenciales de AWS con AWS CLI como se muestra a continuación.

aws configure

Los diversos problemas que surgen durante la instalación se pueden corregir rápidamente con Kiro-cli. Se puede instalar como se muestra a continuación, pero en Windows, descárguelo e instálelo desde Instalación de Kiro. Para ejecutarlo, escriba "kiro-cli" en la terminal.

curl -fsSL https://cli.kiro.dev/install | bash

Configurar un entorno con venv facilita la gestión de paquetes. Configure el entorno como se muestra a continuación.

python -m venv .venv
source .venv/bin/activate

Luego, muévase a la carpeta de GitHub descargada e instale los paquetes adicionales necesarios como se muestra a continuación.

pip install -r requirements.txt

Luego, ejecute Streamlit con el siguiente comando.

streamlit run application/app.py

MCP Inspector

Para probar el servidor MCP en modo de desarrollo, puede usar MCP Inspector. Instale la CLI como se muestra a continuación.

pip install 'mcp[cli]'

Luego, ejecútelo como se muestra a continuación para probar fácilmente el funcionamiento de mcp-server.py. Al ejecutarlo, se proporciona una URL como http://localhost:5173.

mcp dev mcp-server.py

Resultados de ejecución

Uso de RAG mediante MCP

Descargue error_code.pdf y cargue el archivo. Luego, si ingresa algo como "Busque los códigos de error relacionados con la presión de agua entre los errores de la caldera", MCP obtendrá la información de la herramienta y mostrará la información obtenida con la herramienta de búsqueda como se muestra a continuación. En este caso, la herramienta de búsqueda ejecuta Lambda, que consulta el término de búsqueda utilizando Knowledge Base, el servicio RAG totalmente administrado, evalúa la relevancia y entrega solo los documentos relevantes. El agente obtiene la respuesta basándose en la información obtenida de la consulta RAG, como se muestra a continuación.

Uso de búsqueda en Internet mediante MCP

Acceda a smithery-Tavily y obtenga los valores de configuración adecuados para su entorno. A continuación se muestra la información de conexión en formato JSON para Mac/Linux.

{
  "mcpServers": {
    "mcp-tavily": {
      "command": "npx",
      "args": [
        "-y",
        "@smithery/cli@latest",
        "run",
        "mcp-tavily",
        "--key",
        "132c5abd-6f2e-4e42-89a1-d0b1fcb75613"
      ]
    }
  }
}

A continuación se muestra la información configurada por defecto para RAG.

{
  "mcpServers": {
    "search": {
      "command": "python",
      "args": [
        "application/mcp-server.py"
      ]
    }
  }
}

A continuación se muestra la configuración al configurar múltiples servidores MCP.

{
   "mcpServers":{
      "RAG":{
         "command":"python",
         "args":[
            "application/mcp-server.py"
         ]
      },
      "mcp-tavily":{
         "command":"npx",
         "args":[
            "-y",
            "@smithery/cli@latest",
            "run",
            "mcp-tavily",
            "--key",
            "132c5abd-6f2e-4e42-89a1-d0b1fcb75613"
         ]
      }
   }
}

Copie esta información en la Configuración MCP del menú izquierdo como se muestra a continuación.

Luego, seleccione "Agente" en el menú, ingrese "¿Dónde hay un buen restaurante en Gangnam?" y verifique el resultado.

Análisis de costos de AWS

Ingrese "Resuma los costos de AWS del último mes" y verifique el resultado.

Generación de imágenes

En el menú izquierdo, seleccione Agente, elija "image generation" en la configuración MCP, ingrese "Dibuja a una persona corriendo por un hermoso río al atardecer" y verifique el resultado.

### Dibujo de la arquitectura AWS

En el menú, seleccione "Agent(Chat)" y elija "aws diagram" como MCP. Luego, si realiza los comandos secuencialmente: "Recomiéndeme una arquitectura para web hosting con Amazon S3." y "Permítame autenticarme con Cognito.", obtendrá el siguiente resultado.

noname

Uso del intérprete de código

Si pregunta "¿Cuántas r tiene strawberry?", se seleccionará y utilizará "repl_coder" de la lista de Herramientas, como se muestra a continuación.

Almacenamiento

En Tool, seleccione "aws storage" y pregunte "¿Cuál es mi uso total de s3?". El resultado se muestra a continuación.

Si pregunta "¿Cuál es mi uso de almacenamiento de aws?", se comprobarán las capacidades de S3, EFS y EBS y se podrá responder como se indica a continuación.

Referencias

MCP Python SDK

Using MCP with LangGraph agents

MCP From Scratch

Understanding MCP From Scratch

LangChain MCP Adapters

"Vibe Coding" LangGraph apps with llms.txt and MCP

MCP LLMS-TXT Documentation Server

MCP - For Server Developers

Model Context Protocol (MCP) and Amazon Bedrock

Model Context Protocol servers

Langchain.js MCP Adapter

Using LangChain With Model Context Protocol (MCP)

Desktop Commander MCP

Smithery

¡Olvídate de Cursor AI, crea tu propia aplicación de agente #MCP!

The Top 7 MCP-Supported AI Frameworks

Drug Discovery Agent based on Amazon Bedrock

Price Per Token

Claude Code Subagents Collection

Top 5 Open-Source Agentic Frameworks