MCP RAG Server

Um servidor Python leve para Geração Aumentada por Recuperação (RAG) usando AWS Lambda. Ele recupera conhecimento de fontes de dados externas como arXiv e PubMed.

Documentação

Implementando Aplicações MCP

O MCP (Model Context Protocol) está se difundindo rapidamente como uma interface principal para aplicações de IA generativa utilizarem dados externos. Iniciado como um projeto de código aberto da Anthropic em novembro de 2024, atualmente é suportado não apenas pelo Cursor, mas também pela OpenAI. Aqui, explicamos como uma aplicação criada com LangGraph utiliza o MCP por meio do MCP with LangChain. O RAG implementado aqui foi construído com o Knowledge Base, o serviço RAG totalmente gerenciado da Amazon, permitindo realizar facilmente tarefas como extração de texto de documentos, sincronização e chunking, além de analisar imagens/tabelas usando multimodalidade. Aqui, configuramos uma API usando AWS Lambda para que o servidor MCP possa acessar facilmente o RAG.

A arquitetura abaixo mostra a configuração de um Agent com MCP no ambiente AWS. O Agent utiliza a estrutura de servidor/cliente MCP para acessar fontes de dados externas. O cliente MCP se comunica com o servidor MCP via stdio/SSE com base no protocolo JSON-RPC. Ao usar stdio, o servidor MCP é composto por código como Python ou Java e, quando recebe uma solicitação do cliente, coleta ou entrega dados usando RAG, internet, etc. No caso de SSE, o cliente e o servidor MCP se comunicam via IP. Aqui, a interface do aplicativo é construída com Streamlit, e os usuários acessam o aplicativo via navegador usando HTTPS por meio de ALB - CloudFront. Além disso, explicamos o desenvolvimento de aplicações baseadas em MCP usando LangGraph, que é vantajoso para personalização.

Utilização do MCP

Conceitos Básicos do MCP

Os usuários podem se conectar a servidores MCP não apenas por meio de ferramentas de IA instaladas em seus computadores, como Claude Desktop e Cursor, mas também principalmente por meio de aplicações desenvolvidas na forma de Agent. O servidor MCP fornece ao cliente MCP suas capacidades como capabilities em resposta às solicitações e executa as solicitações do cliente. O servidor MCP pode consultar arquivos ou bancos de dados no computador local, bem como obter informações necessárias usando APIs de servidores externos na internet. O Cliente MCP se conecta ao Servidor usando o protocolo JSON-RPC 2.0, podendo escolher entre stdio ou SSE (Server-Sent Events) para transmitir solicitações do Host ao MCP e receber respostas.

A definição e o funcionamento dos principais elementos do MCP são os seguintes:

  • MCP Hosts: Programas/ferramentas de IA que acessam dados por meio do protocolo MCP, como Claude Desktop, Cursor e Aplicações de Agent do Usuário.
  • MCP Clients: Clientes que se conectam 1:1 com o Servidor MCP, podendo se conectar via stdio ou SSE.
  • MCP Servers: Programas leves que informam as capabilities das ferramentas ao Cliente por meio do MCP padronizado, podendo consultar arquivos ou bancos de dados no computador local e obter informações usando APIs externas.
  • Fontes de dados locais: Bancos de dados e dados locais que o servidor MCP pode acessar.
  • Serviços remotos: Sistemas externos acessíveis via API.

O uso do MCP oferece as seguintes vantagens:

  • Acesso a diversas fontes de dados de forma padronizada.
  • Adição de novos recursos por meio de atualizações do servidor MCP sem alterar o código da aplicação.
  • Facilidade de suporte e expansão de IA em toda a organização.

Os Componentes do Servidor MCP incluem os seguintes itens:

  • Tools (controladas pelo modelo): Funções (ferramentas) que o LLM pode chamar para executar tarefas específicas, realizando ações específicas como APIs.
tools = await session.list_tools()
  • Resources (controladas pela aplicação): Fontes de dados que a aplicação de IA generativa pode acessar. Podem obter dados sem cálculos significativos ou efeitos colaterais.
resources = await session.list_resources()
  • Prompts (controlados pelo usuário): Modelos predefinidos usados ao utilizar ferramentas ou recursos, que podem ser selecionados antes da inferência.
prompts = await session.list_prompts()

Arquitetura de Operação

Quando o usuário seleciona o tipo de conversa, o tipo de Agent e o servidor MCP na UI do Streamlit (app.py), o chat.py faz o roteamento por modo. O modo Agent suporta três implementações: LangGraph, Strands e Claude Agent SDK. As configurações do servidor MCP são carregadas em mcp_config.py via 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óduloDescrição
Conversa cotidianachat.general_conversationHistórico de conversa + streaming do Bedrock Runtime invoke_model_with_response_stream
RAGchat.run_rag_with_knowledge_baseBusca no Bedrock Knowledge Base (retrieve) e geração de resposta com o Bedrock Runtime
Agent / Agent (Chat) — langgraphchat.run_langgraph_agentLangGraph StateGraph + LangChain MultiServerMCPClient + ferramentas integradas
Agent / Agent (Chat) — strandschat.run_strands_agentStrands SDK + strands_tools + MCPClientManager + ferramentas integradas
Agent / Agent (Chat) — claudeclaude_agent.run_claude_agentClaude Agent SDK (ClaudeSDKClient) + MCP (backend Bedrock)
Análise de imagemchat.summarize_image / chat.get_image_summarizationAnálise multimodal do ChatBedrock (imagem + texto)
Traduçãochat.translate_textTradução coreano↔inglês
Revisão gramaticalchat.check_grammerRevisão gramatical de coreano e inglês com sugestões de correção

O modo Agent (Chat) usa a mesma implementação de Agent do modo Agent, mas mantém o histórico de conversa com history_mode=Enable. Os servidores MCP podem ser selecionados em múltipla escolha na barra lateral, e as configurações de stdio ou streamable HTTP são mescladas com mcp_config.load_selected_config().

Adaptador LangChain MCP

O Adaptador LangChain MCP é um wrapper leve de código aberto baseado em MIT que permite usar o MCP com agentes LangGraph. A principal função do Adaptador MCP é definir ferramentas para o servidor MCP, consultar informações das ferramentas no cliente MCP e permitir que sejam utilizadas como nós de ferramentas no LangGraph.

Pré-requisitos

Instale o MCP e o Adaptador LangChain MCP conforme abaixo.

pip install mcp langchain-mcp-adapters

Servidor MCP

O servidor MCP para busca RAG pode ser definido conforme abaixo. Ao especificar o transporte do servidor como "stdio", mesmo sem manter o servidor em execução contínua, o cliente pode executar diretamente o código Python do servidor, o que é 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")

Quando o servidor recebe uma solicitação, ele executa a busca RAG com 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'], []

Em relação à descoberta de medicamentos, são suportados arXiv, ChEMBL, ClinicalTrials.gov e PubMed.

Cliente MCP

Quando o cliente MCP visualiza apenas um servidor MCP, pode ser implementado usando stdio_client e StdioServerParameters conforme abaixo. As informações sobre o servidor MCP podem ser lidas de config.json ou usar informações inseridas pelo usuário no Streamlit. Em load_mcp_server_parameters(), o mcp_json é lido e os StdioServerParameters são configurados.

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 o stdio_client com as informações do servidor MCP conforme abaixo. Neste momento, as informações sobre as ferramentas são obtidas com load_mcp_tools. No Agent, as informações das ferramentas são vinculadas e a ação solicitada é executada usando 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 = "답변을 찾지 못하였습니다."

Aqui, usamos um agente LangGraph no estilo ReAct conforme abaixo.

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()

O cliente MCP é executado conforme abaixo. Usamos asyncio para execução assíncrona.

asyncio.run(mcp_agent(query, st))

Aqui, definimos o agente para facilitar a personalização.

Utilização de Servidores MCP

Os servidores Model Context Protocol também fornecem informações sobre os seguintes servidores:

No Smithery, você pode procurar servidores MCP e, ao encontrar o servidor necessário, consultar as informações do servidor MCP em formato JSON para conexão.

As informações do servidor MCP para busca no Google, verificadas no Smithery - Google Search Server, são as seguintes. Requer ID do mecanismo de busca e chave 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\"}"
      ]
    }
  }
}

As informações do servidor em formato JSON podem ser atualizadas conforme abaixo. Abaixo, usamos a busca definida em mcp-server.py.

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

Análise de Custos AWS

Como ferramenta MCP, é possível obter e analisar informações de custos AWS conforme abaixo.

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 usar os 3 resultados de custo acima em gráficos, é necessária a instalação dos seguintes pacotes.

pip install -U kaleido

Geração de Imagens com MCP

Registre uma ferramenta de geração de imagens como em mcp_server_image_generation.py.

A configuração MCP é definida conforme abaixo. Consulte mcp_config.py.

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

Em seguida, gere a imagem como em 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]
    } 

O resultado obtido da image_generation do MCP é exibido conforme abaixo. Consulte chat.py para detalhes.

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 com MCP

Usando o AWS Diagram MCP Server, é possível desenhar diagramas AWS. Consulte mcp_config.py para detalhes.

A configuração MCP usada neste caso é a seguinte.

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

Para desenhar diagramas, instale o graphviz seguindo o Graphviz. No Mac, use o seguinte comando.

brew install graphviz

Documentação AWS com MCP

Usando o AWS Documentation MCP Server, é possível consultar documentos AWS. A configuração MCP usada neste caso é a seguinte. Consulte mcp_config.py para detalhes.

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

Como verificar modelos disponíveis por região

A forma de verificar os modelos disponíveis é a seguinte.

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

Trim de Mensagens

O agente LangGraph (application/langgraph_agent.py do call_model) mantém apenas os últimos N turnos com base em HumanMessage imediatamente antes da chamada do LLM. O messages do estado do LangGraph permanece no checkpointer, e apenas as mensagens enviadas ao modelo são reduzidas. Aplica-se igualmente a history_mode=Enable/Disable.

Valor padrão: MAX_CONTEXT_TURNS = 5 (intenção de "últimos 5 turnos", igual ao SimpleMemory(k=5) do chat normal)

Alteração de configuração:

A constante e a função de trim são definidas em 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]:]

Em call_model, o trim é aplicado após a normalização do conteúdo 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}):
            ...

A configuração do agente é criada em create_agent() de chat.py, e max_turns é transmitido independentemente 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

  • Mantém 5 HumanMessages do usuário e todas as mensagens subsequentes de cada turno
  • 1 turno = 1 HumanMessage + AIMessage, ToolMessage e todo o loop de feedback de ferramentas subsequente
  • Mesmo com múltiplas chamadas de ferramentas, se for a mesma pergunta do usuário, conta como 1 turno

Exemplo (incluindo uso de ferramentas)

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

Se max_turns=2, mantém a partir de Q2:

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

Diferença em relação ao trim por contagem de mensagens

AbordagemQuando N=5
Anterior (contagem de mensagens)Mantém apenas 5 objetos de mensagem → o número de turnos do usuário fica irregular devido ao loop de ferramentas
Atual (turnos de HumanMessage)Mantém 5 perguntas do usuário + todas as respostas de IA/Ferramenta de cada turno

Relação com o Checkpointer

  • Quando history_mode=Enable, o checkpointer MemorySaver armazena todo o histórico da conversa.
  • O trim é para gerenciamento da janela de contexto do LLM e não exclui o histórico armazenado.
  • É possível verificar se o trim foi aplicado por meio de trimmed messages from X to Y (max_turns=5) no CloudWatch (/ecs/...) ou nos logs da aplicação.

Implantação

Implantação no EC2

Acesse o EC2 no console da AWS e selecione Launch an instance. Após selecionar [Launch instance], insira um nome adequado (ex.: es). Em key pair, selecione "Proceed without key pair" e continue.

ec2이름입력

Quando a instância estiver pronta, selecione [Connect] - [EC2 Instance Connect] para acessar conforme abaixo.

image

Em seguida, instale python, pip, git e boto3 conforme abaixo.

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

No caso do Workshop, copie as credenciais no formato abaixo e insira no terminal do EC2.

credential

Obtenha o código-fonte do git conforme abaixo.

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

Inicie a instalação usando installer.py conforme abaixo.

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

As credenciais necessárias para a implementação da API são gerenciadas como segredos. Portanto, como a entrada de credenciais é necessária durante a instalação, prepare as credenciais antecipadamente usando os seguintes métodos:

  • Busca na internet geral: Acesse Tavily Search, cadastre-se e emita a chave de API. Ela começa com tvly-.
  • Busca de clima: Acesse openweathermap e emita a chave de API. Neste caso, selecione o plano de preço "Free".

Quando a instalação for concluída, acesse o CloudFront conforme abaixo para verificar o funcionamento.

cloudfront_address

Quando a infraestrutura não for mais necessária, remova-a usando uninstaller.py.

python uninstaller.py

Atualizando a Aplicação Implantada

Acesse o EC2 no console da AWS, selecione Launch an instance e selecione o ID da instância com o nome "app-for-es-us" conforme abaixo.

image

Selecione [Connect] e depois Session Manager para acessar.

image

Em seguida, atualize conforme abaixo e verifique novamente no navegador.

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

Verificando Logs de Execução

No console EC2, selecione o ID da instância com o nome "app-for-es-us" e acesse usando o Session Manager do EC2.

Primeiro, verifique o ID do container Docker atual conforme abaixo.

sudo docker ps

Em seguida, verifique os logs usando o ID do container conforme abaixo.

sudo docker logs [container ID]

O resultado da execução real é o seguinte.

Executando Localmente

Para utilizar bem o ambiente AWS, é necessário instalar o AWS CLI. Ao implantar no EC2, não é necessária instalação separada. Para instalação local, consulte o comando abaixo.

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

Registre as credenciais AWS usando o AWS CLI conforme abaixo.

aws configure

Vários problemas que ocorrem durante a instalação podem ser corrigidos rapidamente usando o Kiro-cli. Pode ser instalado conforme abaixo, mas no Windows, baixe e instale em Instalação do Kiro. Ao executar, digite "kiro-cli" no shell.

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

Configurar o ambiente com venv facilita o gerenciamento de pacotes. Configure o ambiente conforme abaixo.

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

Em seguida, navegue até a pasta do github baixada e instale os pacotes adicionais necessários conforme abaixo.

pip install -r requirements.txt

Em seguida, execute o Streamlit com o seguinte comando.

streamlit run application/app.py

MCP Inspector

Para testar o servidor MCP no Modo de Desenvolvimento, você pode usar o MCP Inspector. Instale a CLI conforme abaixo.

pip install 'mcp[cli]'

Em seguida, execute conforme abaixo para testar facilmente o funcionamento do mcp-server.py. Ao executar, é fornecida uma URL como http://localhost:5173.

mcp dev mcp-server.py

Resultados de Execução

Consultando e Utilizando RAG com MCP

Baixe error_code.pdf e faça upload do arquivo. Em seguida, insira algo como "Pesquise os códigos de erro relacionados à pressão da água entre os erros da caldeira." conforme abaixo. O MCP obtém as informações da ferramenta e, usando as informações obtidas pela ferramenta de busca, pode exibir as informações abaixo. Neste caso, a ferramenta de busca executa uma lambda, que consulta o termo de busca usando o knowledge base, o serviço RAG totalmente gerenciado, avalia a relevância e entrega apenas os documentos relacionados. O Agent obtém a resposta usando as informações obtidas pela consulta ao RAG, conforme abaixo.

Realizando Buscas na Internet com MCP

Acesse smithery-Tavily e obtenha os valores de configuração adequados ao seu ambiente. Abaixo estão as informações de conexão em formato JSON para Mac/Linux.

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

Abaixo estão as informações padrão configuradas para RAG.

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

Abaixo está a configuração ao definir múltiplos 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 essas informações para a Configuração MCP no menu esquerdo, conforme abaixo.

Em seguida, selecione "Agent" no menu e insira "Quais são os melhores restaurantes perto da estação Gangnam?" conforme abaixo e verifique o resultado.

Análise de Custos AWS

Insira "Resuma os custos AWS do último mês." e verifique o resultado.

Geração de Imagens

No menu esquerdo, selecione Agent, escolha "image generation" na configuração MCP e insira "Desenhe uma pessoa correndo em uma margem bonita ao pôr do sol." e verifique o resultado.

### Desenhando Arquitetura AWS

No menu, selecione "Agent(Chat)" e escolha "aws diagram" no MCP. Em seguida, execute comandos sequenciais: "recomende uma arquitetura para web hosting com Amazon S3." e "permita autenticação usando Cognito." Você obterá o seguinte resultado.

noname

Utilização do Code Interpreter

Ao perguntar "quantos r existem em strawberry?", o "repl_coder" é selecionado na lista de Tools e utilizado, como abaixo.

Storage

Na ferramenta, selecione "aws storage" e pergunte "qual é o meu uso total do s3?". O resultado é o seguinte.

Ao perguntar "qual é o meu uso de armazenamento aws?", é possível verificar a capacidade de S3, EFS e EBS e responder como abaixo.

Referência

MCP Python SDK

Usando MCP com agentes LangGraph

MCP do zero

Entendendo MCP do zero

LangChain MCP Adapters

Aplicativos LangGraph com "Vibe Coding" usando llms.txt e MCP

Servidor de Documentação MCP LLMS-TXT

MCP - Para Desenvolvedores de Servidores

Model Context Protocol (MCP) e Amazon Bedrock

Servidores Model Context Protocol

Langchain.js MCP Adapter

Usando LangChain com Model Context Protocol (MCP)

Desktop Commander MCP

Smithery

Em vez de Cursor AI, vamos criar meu próprio aplicativo de agente #MCP!

Os 7 principais frameworks de IA com suporte a MCP

Agente de Descoberta de Medicamentos baseado em Amazon Bedrock

Preço por Token

Coleção de Subagentes Claude Code

Os 5 principais frameworks agênticos de código aberto