mcp-walmart-ads
Servidor MCP para Walmart Connect Ads (Sponsored Search + Display) — assinatura automática RSA-SHA256, configuração multirregional e documentação da API inclusa.
Documentação
APIs Walmart e Sam's Club
Servidor MCP para três famílias de APIs da Walmart Inc., atrás de uma única superfície de ferramentas:
| Plataforma | APIs | Autenticação |
|---|---|---|
walmart:ads — Walmart Connect | Sponsored Products, Display | Assinatura RSA-SHA256 + token bearer |
walmart:marketplace — Walmart Marketplace | 28 domínios (pedidos, itens, feeds, relatórios, …) | OAuth2 client_credentials |
samsclub:ads — Sam's Club | Sponsored Products | Assinatura RSA-SHA256 + token bearer |
Quatro ferramentas sobre 31 APIs e 424 operações — descoberta, um proxy genérico e um download. Um agente encontra endpoints nas especificações OpenAPI incluídas e os chama; o servidor assina, adquire tokens e monta cabeçalhos.
walmart:ads:sponsored-products:SBAProfileUpdateV2
└─ retailer ─┘└ line ┘└─── api name ───┘└── operationId ──┘
└────────── platform ─────────┘ credentials attach here
Um ID de operação sozinho resolve para um host e um modelo de autenticação. Um sufixo <line>:<name>
correspondente significa a mesma superfície para outro varejista — 13 IDs de operação compartilhados de 90.
Requisitos
- Python 3.13+
- Credenciais para as plataformas que você usar. Configure apenas essas — uma plataforma ausente
simplesmente fica não configurada, e a descoberta funciona sem nenhuma credencial.
- Walmart Connect / Sam's Club — consumer ID, par de chaves RSA, token bearer
- Walmart Marketplace — client ID + secret, e os IDs de anunciante (perfil de vendedor) que eles atendem
Início rápido
Configure sua configuração (veja Configuração), depois execute o servidor:
# Run directly with uvx (no clone needed)
npx -y @modelcontextprotocol/inspector@latest uvx mcp-walmart-ads
# Or run from source
git clone https://github.com/alyiox/mcp-walmart-ads.git
cd mcp-walmart-ads
uv sync
npx -y @modelcontextprotocol/inspector@latest uv run mcp-walmart-ads
Configuração
config.json DEVE estar em ~/.config/mcp-walmart-ads/config.json. O servidor o lê
uma vez na inicialização, então um arquivo corrigido EXIGE reinicialização.
Windows:
~mapeia para%USERPROFILE%(normalmenteC:\Users\<you>), tornando o caminho completo%USERPROFILE%\.config\mcp-walmart-ads\config.json.
Crie o diretório e copie o exemplo:
# Unix-like (macOS, Linux, WSL, …)
mkdir -p ~/.config/mcp-walmart-ads/keys/walmart-ads
cp config.example.json ~/.config/mcp-walmart-ads/config.json
# Windows (PowerShell)
New-Item -ItemType Directory -Force "$env:USERPROFILE\.config\mcp-walmart-ads\keys\walmart-ads"
Copy-Item config.example.json "$env:USERPROFILE\.config\mcp-walmart-ads\config.json"
Formato
platforms.<platform>.regions.<region>.<environment> = <auth block>
<platform> é o prefixo de dois segmentos com o qual um ID de API começa, então uma chave de configuração é literalmente
o valor que você passa como parâmetro da ferramenta platform — nada para traduzir.
O formato do bloco de autenticação segue o modelo de autenticação da plataforma. Existe exatamente um formato por plataforma, então nenhum campo discriminador é necessário.
Plataformas com assinatura (walmart:ads, samsclub:ads):
{
"platforms": {
"walmart:ads": {
"regions": {
"us": {
"production": {
"consumer_id": "your-consumer-id",
"private_key": "./keys/walmart-ads/us-prod.pem",
"private_key_version": "1",
"bearer_token": "your-bearer-token",
"base_urls": {
"sponsored-products": "https://developer.api.walmart.com/api-proxy/service/WPA/Api/v1",
"display": "https://developer.api.walmart.com/api-proxy/service/display/api/v1"
}
}
}
}
}
}
}
| Campo | Observações |
|---|---|
consumer_id | Consumer ID da Partner Network |
private_key | Caminho para a chave privada RSA (PEM). Caminhos relativos são resolvidos em relação ao diretório de configuração |
private_key_version | String de versão da chave (padrão "1") |
bearer_token | Token bearer OAuth |
base_urls.<api> | Um por API na superfície de descoberta da plataforma. Chaves PODEM ser simples (sponsored-products) ou totalmente qualificadas (walmart:ads:sponsored-products); chaves extras são permitidas para as especificações auxiliares alcançadas por método+caminho brutos |
Nomes de ambiente são de forma livre aqui — a Walmart pode emitir um tenant apenas production, ou
production e staging.
Plataforma OAuth2 (walmart:marketplace):
{
"platforms": {
"walmart:marketplace": {
"regions": {
"us": {
"production": {
"credentials": [
{
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"advertisers": [
{ "id": 7060158, "partner_id": "10001234" },
{ "id": 7060159 }
]
}
]
}
}
}
}
}
}
environment DEVE ser production ou sandbox; URLs base são fixas pelo servidor e
ausentes do arquivo. IDs de anunciante ficam aninhados sob a credencial que os atende, então um
secret aparece exatamente uma vez e uma referência de anunciante solta é estruturalmente
impossível. partner_id é por vendedor porque duas operações payments o exigem como
WM_PARTNER_ID; um valor todo-zero é lido como ausente, já que é o que uma configuração gerada
escreve para um vendedor sem um, e scripts/backfill_partner_ids.py preenche as lacunas a partir da
Walmart.
Regiões são um namespace, não uma rota — toda região walmart:marketplace alcança os mesmos
hosts. O nível existe porque IDs de anunciante são únicos apenas dentro de uma região.
Dividindo a configuração
Um bloco walmart:marketplace preenchido chega a dezenas de kilobytes de credenciais, 88% do
arquivo aqui, e uma vírgula perdida ao editá-lo derruba todas as plataformas: uma falha
de análise precede a validação por plataforma. As plataformas PODEM, portanto, viver em arquivos drop-in
sob config.d/, mesclados sobre a base:
~/.config/mcp-walmart-ads/
├── config.json # server-wide settings, and any platforms you like
├── config.d/
│ ├── walmart-marketplace.json # only a "platforms" object
│ └── samsclub-ads.json
└── keys/
- Um drop-in DEVE declarar apenas
platforms; configurações de todo o servidor ficam emconfig.json. - Uma plataforma declarada em dois arquivos é um erro nomeando ambos — nunca precedência silenciosa.
- Apenas
*.jsondiretamente emconfig.d/é lido, então.bake arquivos de troca do editor são ignorados. - Um arquivo que falha ao analisar custa apenas suas próprias plataformas; o resto continua funcionando.
- Caminhos
private_keyrelativos são resolvidos em relação ao diretório deconfig.jsonde qualquer forma, então mover uma plataforma paraconfig.d/não precisa de edições de caminho. - Sem diretório
config.d/significa nenhuma mudança de comportamento.
Um bloco malformado para uma plataforma NÃO DEVE impedir o carregamento das outras. Leia
wmt://platforms para ver quais carregaram e quais regiões e ambientes elas declaram: uma que
falhou não tem regiões, e ler um de seus ambientes retorna a mensagem do próprio carregador —
qual arquivo, quais campos, e que uma correção precisa de reinicialização.
Opções de nível superior
| Campo | Padrão | Observações |
|---|---|---|
response_cache_ttl | 3600 | Segundos que um corpo truncado ou download permanece legível em seu URI de recurso |
truncate_threshold | 2048 | Bytes de resposta retornados inline antes de truncar para uma prévia |
spec_refresh | {"auto": true, "interval": 7} | Atualização de especificação em segundo plano. auto liga ou desliga a varredura; interval é dias entre varreduras, e PODE ser fracionário |
Mercado → tenant (wap-tenant-id)
Passe tenant em call_endpoint e download_file para mercados walmart:ads fora dos EUA
(WMT_CA, WMT_MX, WBD_OD, …). Omita para os EUA e para walmart:marketplace.
Ferramentas
list_endpoints
Lista operações em todas as APIs, com filtros opcionais.
| Parâmetro | Observações |
|---|---|
query | Substring sem diferenciar maiúsculas/minúsculas no ID da operação, caminho ou resumo |
api | Limitar a uma API, ex.: walmart:marketplace:order-management |
platform | Limitar a uma plataforma — walmart:ads, walmart:marketplace, samsclub:ads (enum do schema) |
tag | Filtrar por tag OpenAPI |
method | Filtrar por verbo HTTP — GET, POST, PUT, PATCH, DELETE (enum do schema) |
IDs de operação retornados são qualificados (api:operationId) e passam direto para
describe_endpoint ou call_endpoint.
describe_endpoint
Uma operação mais cada entrada components.schemas alcançável a partir dela, para que um corpo
de requisição possa ser construído sem a especificação completa. Cabeçalhos de autenticação e QoS gerenciados pelo servidor são omitidos.
| Parâmetro | Observações |
|---|---|
operation_id | Qualificado (api:operationId), ou simples quando inequívoco |
api | API para resolver um ID simples, ex.: walmart:ads:sponsored-products |
call_endpoint
Executa uma requisição autenticada contra qualquer plataforma configurada. Assinatura, aquisição de token com cache por credencial e atualização single-flight, e uma nova tentativa após um 401 acontecem tudo no lado do servidor.
| Parâmetro | Observações |
|---|---|
region, environment | Obrigatórios. Origem: config |
operation_id | Qualificado ou simples. Resolve API, plataforma, método, caminho e cabeçalhos necessários |
api | Obrigatório com method + path brutos; caso contrário, inferido de operation_id. Aceita as duas especificações walmart:ads auxiliares |
method, path | Rota bruta, alcançando endpoints alfa/beta/não publicados ausentes das especificações |
path_params | Valores para {placeholders} no caminho |
params, body | Query string e corpo JSON |
file_path | Envia o arquivo como multipart/form-data — uploads de feed do Marketplace. Combine com o parâmetro de query feedType |
advertiser_id | DEVE ser fornecido em walmart:marketplace, onde seleciona a credencial. Opcional nas plataformas de anúncios, onde é enviado como X-Advertiser-ID |
tenant | Tenant WAP para regiões walmart:ads fora dos EUA |
Uma resposta maior que truncate_threshold é pré-visualizada inline, com o corpo completo em
wmt://responses/{request_id} e um cURL reproduzível em wmt://curl/{request_id} —
tokens bearer, tokens de acesso e assinaturas substituídos por placeholders.
download_file
Baixa um relatório, etiqueta ou snapshot de um endpoint autenticado. Forneça um url completo
(a URL details de uma sondagem de snapshot de display, por exemplo), ou operation_id, ou api com
method + path. platform é obrigatório apenas para um url simples.
Com dest_path os bytes são gravados lá. Sem ele, são descompactados com gunzip quando compactados
e armazenados em cache, e o resultado carrega cached_at — um payload binário sem dest_path pede
um. Redirecionamentos são seguidos, mantendo cabeçalhos de autenticação em um Location relativo ou do mesmo host
e descartando credenciais entre hosts; o resultado inclui urls, o caminho de saltos.
Especificações
33 documentos OpenAPI acompanham a wheel. Uma atualização grava cópias atualizadas em
~/.cache/mcp-walmart-ads/specs/, que tem precedência sobre o pacote na leitura. O pacote nunca é
gravado em tempo de execução, então permanece como o piso ao qual um cache danificado ou ausente recorre.
De onde vêm
A Walmart não publica arquivos OpenAPI, mas cada página de referência do ReadMe hidrata seu HTML com
os UUIDs de registro de seus documentos, e https://dash.readme.com/api/v1/api-registry/<uuid>
serve a especificação completa sem autenticação. Isso cobre Walmart Connect e todos os 28 domínios
do Marketplace. A Sam's Club não publica nenhum, então sua especificação é escrita manualmente a partir da documentação
para desenvolvedores: scripts/build_samsclub_spec.py regenera um candidato desses documentos, e o
fluxo de trabalho agendado spec drift abre um PR quando eles mudam, como um portão de revisão humana. O
candidato nunca é enviado e nunca é carregado em tempo de execução.
Os documentos são armazenados literalmente como o upstream os serviu, então um diff de atualização mostra exatamente
o que mudou. Exemplos inline superdimensionados e metadados x-readme são removidos no carregamento
em vez de no disco, o que mantém essa redução reajustável sem baixar nada novamente.
Mantendo-os atualizados
As especificações são atualizadas em segundo plano: uma vez na inicialização, depois a cada spec_refresh.interval dias
(7 por padrão). Defina auto para false para parar a varredura — o intervalo é lembrado para
quando você o religar, e a atualização manual ainda funciona.
Para atualizar agora, tendo atingido um endpoint que a especificação incluída não tem:
# Installed with uvx (no clone)
uvx mcp-walmart-ads --refresh
# Or from a source checkout
uv run mcp-walmart-ads --refresh
Qualquer forma varre todas as especificações independentemente do intervalo e grava o mesmo cache de usuário,
imprimindo uma linha por documento: written, unchanged, ou error.
Não há deliberadamente nenhuma ferramenta para isso. Uma especificação desatualizada é indistinguível de uma atual de dentro de uma sessão — ela simplesmente não tem um endpoint — então um agente solicitado a decidir ou nunca atualizaria ou atualizaria supersticiosamente após uma falha não relacionada. O gatilho pertence fora da sessão.
Um documento DEVE produzir pelo menos uma operação antes de ser instalado, então um upstream respondendo
200 com um corpo de erro não pode envenenar o cache, e um documento byte-idêntico
é deixado em paz. Um arquivo em cache que não carrega é descartado e a leitura recorre ao
pacote. Servidores coordenam através de spec-state.json na raiz do cache, que registra
quando cada especificação foi tentada pela última vez e mantém uma concessão para que um processo varra por vez — cada
sessão de cliente executa seu próprio processo de servidor, e sem ele cada um rebaixaria todos os 33.
Reconstruindo o pacote
Uma etapa de mantenedor, e não a mesma coisa que --refresh: isso atualiza seu cache, isso
atualiza as cópias que acompanham a wheel.
# Registry-sourced specs only, by default
uv run python scripts/fetch_specs.py
uv run python scripts/fetch_specs.py walmart:ads:sponsored-products walmart:marketplace:order-management
# Regenerate the Sam's Club candidate spec for review
uv run --group spec-build python scripts/build_samsclub_spec.py
Recursos MCP
| URI do recurso | Descrição |
|---|---|
wmt://platforms | Cada plataforma, seu modelo de autenticação, e as regiões e ambientes que ela declara |
wmt://platforms/{platform}/apis | Os ids de api dessa plataforma |
wmt://platforms/{platform}/apis/{name} | Uma api: título, versão, contagem de operações, e suas tags com uma contagem cada — os valores legais de list_endpoints(tag=…) |
wmt://platforms/walmart:marketplace/regions/{region}/{environment}/advertisers | Ids de anunciante mapeados para seu Walmart Partner ID (null quando não definido) |
wmt://platforms/{platform}/regions/{region}/{environment}/hosts | Ids de api mapeados para a URL base que uma chamada alcança, ou * para cada api cujo host o servidor possui |
wmt://responses/{request_id} | Corpo completo de uma resposta truncada ou de um download em cache (em memória, TTL a partir da configuração) |
wmt://curl/{request_id} | cURL reproduzível para uma solicitação anterior, com credenciais substituídas por placeholders |
Exemplos de hosts MCP
Cursor
Adicione ao .cursor/mcp.json:
{
"mcpServers": {
"walmart": {
"command": "uvx",
"args": ["mcp-walmart-ads"]
}
}
}
Claude Code
Adicione à configuração MCP do seu Claude Code:
{
"mcpServers": {
"walmart": {
"command": "uvx",
"args": ["mcp-walmart-ads"]
}
}
}
Codex
[mcp_servers.walmart]
command = "uvx"
args = ["mcp-walmart-ads"]
OpenCode
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"walmart": {
"type": "local",
"enabled": true,
"command": ["uvx", "mcp-walmart-ads"]
}
}
}
GitHub Copilot
{
"inputs": [],
"servers": {
"walmart": {
"type": "stdio",
"command": "uvx",
"args": ["mcp-walmart-ads"]
}
}
}
Desenvolvimento
uv sync --group dev
uv run ruff check src/ tests/ scripts/
uv run ruff format --check src/ tests/ scripts/
uv run pyright
uv run pytest tests/ -v
Contribuindo
Issues e pull requests são bem-vindos. Mantenha as mudanças focadas; ruff check,
ruff format --check, pyright, e pytest devem passar todos.