O Protocolo de Contexto do Modelo (MCP) está rapidamente se tornou um padrão para capacitar Modelos de Linguagem de Grande Escala (LLMs) como Claude, ChatGPT e outros a interagir com o mundo exterior. Definindo ferramentas de maneira estruturada, o MCP permite que os LLMs solicitem ações, obtenham dados em tempo real ou interajam com APIs externas, superando seus dados de treinamento estáticos.
No entanto, a implantação desses "servidores" MCP (que fornecem as ferramentas) frequentemente apresenta um desafio, especialmente em ambientes modernos de nuvem. Muitas implementações iniciais do MCP foram projetadas para execução local, comunicando-se por meio de entrada/saída padrão (stdio) ou usando protocolos como Server-Sent Events (SSE) para streaming. Embora funcionais, essas abordagens frequentemente dependem de conexões persistentes e comportamentos com estado, tornando-as inadequadas para plataformas escaláveis, sem estado, orientadas a eventos como o AWS Lambda.
O AWS Lambda oferece enormes benefícios: escalonamento automático, eficiência de custo sob demanda, e zero sobrecarga de gerenciamento de servidor. Como podemos superar essa lacuna e executar servidores MCP robustos e prontos para produção neste ambiente sem servidor?
Apresentando MCPEngine, uma implementação Python de código aberto do MCP, especialmente projetada para abordar esses desafios. O MCPEngine suporta HTTP transmitível juntamente com SSE, tornando-o totalmente compatível com o modelo de solicitação/resposta do AWS Lambda. Também agrupa recursos essenciais para implantações de produção, incluindo suporte de autenticação embutido e empacotamento simplificado.
Este artigo explora como aproveitar o MCPEngine para construir e implantar servidores MCP no AWS Lambda, cobrindo ferramentas sem estado, gerenciamento de estado e autenticação.
Apidog-MCP-Server permite que o Cursor leia diretamente a documentação da API, que pode ser documentação publicada online ou até mesmo arquivos locais OpenAPI.
Ao fazer do seu design de API a fonte de verdade para a IA, o Servidor MCP da Apidog facilita tarefas como geração de código com base em esquemas, busca inteligente por endpoints e garantindo que as modificações de código estejam alinhadas perfeitamente com o contrato da API, agilizando assim o fluxo de trabalho de desenvolvimento.
Estamos empolgados em compartilhar que o suporte ao MCP estará disponível em breve no Apidog! 🚀
— Apidog (@ApidogHQ) 19 de março de 2025
O Servidor MCP da Apidog permite que você forneça documentação da API diretamente à IA Agentic, supercarregando sua experiência de codificação vibe! Quer você esteja usando o Cursor, o Cline ou o Windsurf - isso tornará seu processo de desenvolvimento mais rápido e fluido.… pic.twitter.com/ew8U38mU0K

Conceitos Básicos: MCPEngine e Lambda
Antes de mergulhar na implantação, vamos entender os principais componentes do MCPEngine para a integração com o Lambda:
MCPEngine
: A classe central que orquestra suas ferramentas e gerencia a comunicação do MCP.@engine.tool()
Decorador: Registra uma função Python como uma ferramenta MCP. O nome da função se torna o nome da ferramenta, e sua docstring serve como a descrição fornecida ao LLM.engine.get_lambda_handler()
: Este método gera uma função de manipulador compatível com o AWS Lambda. Você expõe este manipulador, e o MCPEngine cuida de traduzir a carga útil do evento Lambda em solicitações MCP e formatar as respostas.
Construindo uma Ferramenta Simples sem Estado
Vamos começar com o básico: uma ferramenta sem estado implantada no Lambda. Este exemplo fornece uma ferramenta simples de saudação.
Pré-requisitos:
- Python 3.8+
- Uma conta AWS com permissões para gerenciar Lambda, ECR e IAM.
- Docker instalado localmente.
- AWS CLI configurado.
1. Instale o MCPEngine:
pip install mcpengine[cli,lambda]
2. Crie o Aplicativo (app.py
):
# app.py
from mcpengine import MCPEngine, Context
# Inicialize o motor
engine = MCPEngine()
@engine.tool()
def personalized_greeting(name: str) -> str:
"""
Gera uma saudação amigável para o nome especificado.
Use esta ferramenta quando solicitado a cumprimentar alguém.
"""
# Lógica simples sem estado
return f"Olá, {name}! Bem-vindo ao mundo MCP sem servidor."
# Obtenha a função manipuladora do Lambda
handler = engine.get_lambda_handler()
Este código define uma única ferramenta, personalized_greeting
, que recebe um name
e retorna uma string. A variável handler
é o que o AWS Lambda invocará.
Fluxo de Trabalho de Implantação: Código para a Nuvem
Implantar um aplicativo MCPEngine no Lambda envolve containerizá-lo com Docker, empurrá-lo para o Amazon Elastic Container Registry (ECR) e configurar a função Lambda.
1. Dockerize o Aplicativo (Dockerfile
):
# Use a imagem base oficial do AWS Lambda Python
FROM public.ecr.aws/lambda/python:3.12
# Defina o diretório de trabalho no contêiner
WORKDIR ${LAMBDA_TASK_ROOT}
# Copie os requisitos primeiro para aproveitar o cache do Docker
COPY requirements.txt .
# Instale as dependências (assumindo que mcpengine esteja listado em requirements.txt)
# Ou instale diretamente: RUN pip install --no-cache-dir mcpengine[cli,lambda]
RUN pip install --no-cache-dir -r requirements.txt
# Copie o restante do código do aplicativo
COPY app.py .
# Defina o comando para executar a função manipuladora (app.handler significa handler em app.py)
CMD ["app.handler"]
(Certifique-se de ter um arquivo requirements.txt
listando mcpengine[cli,lambda]
ou modifique o comando RUN
de acordo).
2. Construa e Envie a Imagem Docker para o ECR:
Primeiro, crie um repositório ECR (substitua <region>
e <repo-name>
):
aws ecr create-repository --repository-name <repo-name> --region <region>
Observe o ID da sua Conta AWS e o URI do repositório na saída (<account-id>.dkr.ecr.<region>.amazonaws.com/<repo-name>
).
Agora, construa, marque e envie a imagem:
# Autentique o Docker com ECR
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com
# Construa a imagem (use --platform para builds de arquitetura cruzada, se necessário)
docker build --platform=linux/amd64 -t <repo-name>:latest .
# Marque a imagem para o ECR
docker tag <repo-name>:latest <account-id>.dkr.ecr.<region>.amazonaws.com/<repo-name>:latest
# Envie a imagem para o ECR
docker push <account-id>.dkr.ecr.<region>.amazonaws.com/<repo-name>:latest
3. Crie e Configure a Função Lambda:
Primeiro, você precisará de uma função de execução IAM para o Lambda. Se você não tiver uma, crie uma básica:
# (Simplificado - ajuste a política de confiança e permissões conforme necessário)
aws iam create-role --role-name lambda-mcp-role --assume-role-policy-document '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"},"Action": "sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name lambda-mcp-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Agora, crie a função Lambda usando a imagem ECR (substitua os espaços reservados):
aws lambda create-function \
--function-name mcp-greeter-function \
--package-type Image \
--code ImageUri=<account-id>.dkr.ecr.<region>.amazonaws.com/<repo-name>:latest \
--role arn:aws:iam::<account-id>:role/lambda-mcp-role \
--timeout 30 \
--memory-size 512 \
--region <region>
4. Exponha via URL da Função:
Para tornar a Lambda chamável via HTTP sem o API Gateway, crie uma URL da Função:
aws lambda create-function-url-config \
--function-name mcp-greeter-function \
--auth-type NONE \
--region <region>
# Adicione permissão para acesso público (ajuste se a autenticação for necessária)
aws lambda add-permission \
--function-name mcp-greeter-function \
--statement-id FunctionURLAllowPublicAccess \
--action lambda:InvokeFunctionUrl \
--principal '*' \
--function-url-auth-type NONE \
--region <region>
Observe a URL da Função retornada pelo comando create-function-url-config
. Seu servidor MCP sem estado agora está ativo!
Gerenciando Estado com o Contexto lifespan
Lambda é sem estado, mas muitas ferramentas precisam acessar bancos de dados, pools de conexão ou outros recursos inicializados na inicialização. O MCPEngine aborda isso com o argumento lifespan
, que aceita um gerenciador de contexto assíncrono.
A função lifespan
executa seu código de configuração (antes de yield
) quando o contêiner Lambda inicia e seu código de limpeza (após yield
) quando o contêiner é encerrado. O valor gerado se torna disponível em suas funções de ferramenta via o objeto ctx
(Contexto).
Vamos construir um simples registrador de eventos que armazena eventos em um banco de dados RDS Postgres.
1. Modifique app.py
:
# app.py (Exemplo com Estado)
import os
import psycopg2
from contextlib import asynccontextmanager
from mcpengine import MCPEngine, Context
# Assume que os detalhes da conexão do DB estão em variáveis de ambiente
DB_HOST = os.environ.get("DB_HOST")
DB_USER = os.environ.get("DB_USER")
DB_PASS = os.environ.get("DB_PASS")
DB_NAME = os.environ.get("DB_NAME")
@asynccontextmanager
async def db_connection_manager():
"""Gerencia o pool de conexão do banco de dados."""
conn = None
try:
print("Estabelecendo conexão com o DB...")
conn = psycopg2.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASS,
dbname=DB_NAME
)
# Cria a tabela se não existir (exemplo simples)
with conn.cursor() as cur:
cur.execute("""
CREATE TABLE IF NOT EXISTS events (
id SERIAL PRIMARY KEY,
event_name TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT now()
);
""")
conn.commit()
print("Conexão com o DB pronta.")
yield {"db_conn": conn} # Torne a conexão disponível via ctx.db_conn
finally:
if conn:
print("Fechando conexão com o DB.")
conn.close()
# Inicialize o motor com o gerenciador de lifespan
engine = MCPEngine(lifespan=db_connection_manager)
@engine.tool()
def log_event(event_name: str, ctx: Context) -> str:
"""Registra um evento com o nome fornecido no banco de dados."""
try:
with ctx.db_conn.cursor() as cur:
cur.execute("INSERT INTO events (event_name) VALUES (%s)", (event_name,))
ctx.db_conn.commit()
return f"Evento '{event_name}' registrado com sucesso."
except Exception as e:
# Tratamento básico de erros
ctx.db_conn.rollback()
return f"Erro ao registrar evento: {e}"
@engine.tool()
def get_latest_events(limit: int = 5, ctx: Context) -> list[str]:
"""Recupera os últimos eventos registrados no banco de dados."""
try:
with ctx.db_conn.cursor() as cur:
cur.execute("SELECT event_name, timestamp FROM events ORDER BY timestamp DESC LIMIT %s", (limit,))
events = [f"[{row[1].strftime('%Y-%m-%d %H:%M:%S')}] {row[0]}" for row in cur.fetchall()]
return events
except Exception as e:
return [f"Erro ao recuperar eventos: {e}"]
# Obtenha o manipulador do Lambda
handler = engine.get_lambda_handler()
2. Considerações de Implantação:
- Banco de Dados: Você precisa de uma instância RDS acessível (ou outro banco de dados).
- Rede: Configure as configurações de VPC da função Lambda para permitir acesso à instância RDS (Grupos de Segurança, Sub-redes).
- Variáveis de Ambiente: Passe
DB_HOST
,DB_USER
,DB_PASS
,DB_NAME
como variáveis de ambiente para a função Lambda. - IAM: O papel de execução do Lambda pode precisar de permissões adicionais se acessar outros serviços AWS (por exemplo, Secrets Manager para credenciais do DB).
Atualize o Dockerfile
, se necessário (por exemplo, para instalar psycopg2-binary
), reconstruir/enviar a imagem e atualizar o código e a configuração da função Lambda (variáveis de ambiente, configurações de VPC).
Protegendo Ferramentas com Autenticação
Ferramentas de produção precisam de autenticação. O MCPEngine se integra com provedores OpenID Connect (OIDC) como Google, AWS Cognito, Auth0, etc.
1. Configure o Provedor OIDC:
Configure um ID de cliente OAuth com seu provedor escolhido (por exemplo, Google Cloud Console). Você precisará do Client ID e, potencialmente, do Client Secret (dependendo do fluxo).
2. Atualize app.py
para Autenticação:
# app.py (Exemplo Autenticado - Trechos)
import os
# ... outras importações ...
from mcpengine import MCPEngine, Context, GoogleIdpConfig # Ou outro IdpConfig
# ... db_connection_manager ...
# Configure o IDP - usando o Google como exemplo
# Assume que GOOGLE_CLIENT_ID está definido como uma variável de ambiente
google_config = GoogleIdpConfig(
client_id=os.environ.get("GOOGLE_CLIENT_ID")
# o emissor pode frequentemente ser inferido, ou definido explicitamente
)
# Inicialize o motor com lifespan e configuração do IDP
engine = MCPEngine(
lifespan=db_connection_manager,
idp_config=google_config
)
# Proteja a ferramenta log_event
@engine.auth() # Adicione este decorador
@engine.tool()
def log_event(event_name: str, ctx: Context) -> str:
"""Registra um evento com o nome dado no banco de dados. Requer autenticação."""
# Acesse as informações do usuário autenticado, se necessário: user_email = ctx.user.email
user_email = ctx.user.email if ctx.user else "desconhecido"
print(f"Usuário autenticado: {user_email}")
try:
# ... (a lógica do banco de dados continua a mesma) ...
return f"Evento '{event_name}' registrado com sucesso por {user_email}."
except Exception as e:
# ... tratamento de erros ...
return f"Erro ao registrar evento para {user_email}: {e}"
# get_latest_events pode permanecer não autenticado ou ser protegido também
@engine.tool()
def get_latest_events(limit: int = 5, ctx: Context) -> list[str]:
# ... (a lógica permanece a mesma) ...
# Obtenha o manipulador do Lambda
handler = engine.get_lambda_handler()
Principais Alterações:
- Importou
GoogleIdpConfig
(ou o apropriado para seu provedor). - Instanciou
MCPEngine
com o argumentoidp_config
. - Adicionou o decorador
@engine.auth()
acima de@engine.tool()
para a(s) função(ões) que requerem autenticação. O MCPEngine automaticamente rejeitará solicitações sem um token JWT válido verificado contra as chaves públicas do IDP. - As informações do usuário autenticado (dos pedidos JWT) estão disponíveis via
ctx.user
.
3. Implantação:
- Passe as variáveis de ambiente necessárias para autenticação (por exemplo,
GOOGLE_CLIENT_ID
) para sua função Lambda. - Reconstrua/envie a imagem e atualize a função Lambda.
Conectando um Cliente LLM
Uma vez que seu servidor MCP esteja implantado no Lambda com uma URL da Função, você pode conectar clientes compatíveis. Usar mcpengine proxy
é uma maneira conveniente de conectar clientes como Claude:
mcpengine proxy <nome-do-serviço-escolhido> <url-da-função-lambda> --mode http --claude
Se usar autenticação:
mcpengine proxy <nome-do-serviço-escolhido> <url-da-função-lambda> \
--mode http \
--claude \
--client-id <seu-client-id-google> \
--client-secret <seu-client-secret-google> # Necessário para o fluxo de aquisição de token
Este comando executa um proxy local ao qual Claude se conecta. O proxy então encaminha as solicitações via HTTP para a sua URL da Função Lambda, lidando com o fluxo de autenticação, se configurado. O LLM agora pode descobrir e invocar suas ferramentas sem servidor.
Conclusão
Implantar servidores MCP no AWS Lambda desbloqueia uma escalabilidade incrível e eficiência operacional para estender as capacidades dos LLMs. Implementações tradicionais do MCP frequentemente lutam em ambientes sem estado, mas o MCPEngine fornece uma solução robusta e de código aberto. Ao suportar HTTP transmitível, oferecer gerenciamento de contexto via lifespan
, e integrar-se perfeitamente com OIDC para autenticação, o MCPEngine torna o MCP sem servidor não apenas possível, mas prático para casos de uso em produção. Quer você esteja construindo ferramentas simples sem estado ou aplicativos complexos, com estado e autenticados, o MCPEngine combinado com o AWS Lambda oferece uma plataforma poderosa para a próxima geração de interações impulsionadas por IA.
Quer uma plataforma integrada, Tudo-em-Um, para sua Equipe de Desenvolvedores trabalharem juntos com máxima produtividade?
Apidog atende todas as suas demandas, e substitui o Postman a um preço muito mais acessível!