Back to Directory/Search & Knowledge

Walmart & Sam's Club APIs

MCP server for Walmart Connect Ads, Sam's Club Sponsored Ads, and Walmart Marketplace APIs

Search & KnowledgePythonv0.5.1

Walmart APIs

CI PyPI Python 3.13+ License: MIT

MCP server for three Walmart Inc. API families, behind one tool surface:

PlatformAPIsAuth
walmart:ads — Walmart ConnectSponsored Products, DisplayRSA-SHA256 signature + bearer token
walmart:marketplace — Walmart Marketplace28 domains (orders, items, feeds, reports, …)OAuth2 client_credentials
samsclub:ads — Sam's ClubSponsored ProductsRSA-SHA256 signature + bearer token

Five tools over 31 apis and 424 operations:

walmart:ads:sponsored-products:SBAProfileUpdateV2
└─ retailer ─┘└ line ┘└─── api name ───┘└── operationId ──┘
   └────────── platform ─────────┘  credentials attach here

Spec-driven discovery (list_endpoints, describe_endpoint), a generic API proxy (call_endpoint), a downloader (download_file), and a runtime spec refresher (refresh_specs). The agent discovers endpoints from bundled OpenAPI specs and calls them; the server handles signing, token acquisition, and header construction.

Features

  • Hierarchical api ids — <retailer>:<line>:<name>, e.g. walmart:ads:sponsored-products, walmart:marketplace:order-management, samsclub:ads:sponsored-products. An operation id appends :operationId. Credentials attach at the two-segment prefix, so an operation id alone resolves to a host and an auth model without the caller naming either
  • One naming convention, two retailers — apis whose <line>:<name> suffix matches cover the same surface for different retailers (walmart:ads:sponsored-products and samsclub:ads:sponsored-products), so an agent can move what it knows across; the overlap is partial, 13 shared operation ids of 90
  • Spec-driven discovery — list/describe endpoints from 33 bundled OpenAPI specs, refreshable at runtime; describe_endpoint returns an operation plus its full components.schemas closure and strips the headers the server owns
  • Any endpoint — call by operation id or raw method+path; raw paths reach alpha/beta/unpublished endpoints absent from the specs
  • Both auth models — per-request RSA-SHA256 signing for the ads platforms; OAuth2 token acquisition with per-credential caching, single-flight refresh, and one retry after a 401 for Marketplace
  • Per-platform config isolation — a malformed block for one platform does not stop the others loading, and discovery works with no credentials at all
  • Credential-safe cURL — every cached cURL replaces bearer tokens, access tokens, and signatures with placeholders
  • Large responses truncated, with the full body available at an MCP resource URI

Requirements

  • Python 3.13+
  • Credentials for whichever platforms you use:
    • Walmart Connect / Sam's Club — consumer ID, RSA key pair, bearer token
    • Walmart Marketplace — client ID + secret, and the advertiser (seller profile) ids they serve

Quick start

Set up your config (see Configuration), then run the server:

# 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

Configuration

The config file lives under your home directory at ~/.config/mcp-walmart-ads/config.json.

Windows note: ~ maps to %USERPROFILE% (typically C:\Users\<you>), so the full path is %USERPROFILE%\.config\mcp-walmart-ads\config.json.

1. Create the config directory and copy the example

# 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"

2. Fill in your credentials. Configure only the platforms you use — an absent platform is simply unconfigured, and the discovery tools keep working regardless.

Shape

platforms.<platform>.regions.<region>.<environment> = <auth block>

<platform> is the two-segment prefix an api id starts with, so a config key is literally the value you pass as the platform tool parameter — nothing to translate.

The auth block's shape follows the platform's auth model. There is exactly one shape per platform, so no discriminator field is needed.

Signature platforms (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"
            }
          }
        }
      }
    }
  }
}
FieldNotes
consumer_idPartner Network consumer ID
private_keyPath to the RSA private key (PEM); relative paths resolve against the config directory
private_key_versionKey version string (default "1")
bearer_tokenOAuth bearer token
base_urls.<api>One per api in the platform's discovery surface. Keys may be bare (sponsored-products) or fully qualified (walmart:ads:sponsored-products). Extra keys are allowed for the auxiliary specs reached by raw method+path

Environment names are free-form for these platforms — Walmart may issue a tenant only production, or production + staging.

OAuth2 platform (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 }
                ]
              }
            ]
          }
        }
      }
    }
  }
}

Advertiser ids nest under the credential that serves them, so a secret appears exactly once and a dangling advertiser reference is structurally impossible. partner_id is per-seller because two payments operations require it as WM_PARTNER_ID; an all-zero value is read as absent, since that is what a generated config writes for a seller without one. scripts/backfill_partner_ids.py fills the absent ones from Walmart. Base URLs are fixed by the server and absent from the file; environment must be production or sandbox.

Regions are a namespace, not a route — for walmart:marketplace every region reaches the same hosts. The level exists because advertiser ids are only unique within a region.

Splitting the config

A populated walmart:marketplace block can be tens of kilobytes of credentials — 88% of the file here — and a stray comma while editing it takes down every platform, because a parse failure happens before any per-platform validation. So platforms may live in drop-in files under config.d/, merged over the 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/
  • A drop-in may declare only platforms; server-wide settings stay in config.json.
  • A platform declared in two files is an error naming both — never silent precedence.
  • Only *.json directly in config.d/ is read, so .bak and editor swap files are ignored.
  • A file that fails to parse costs only its own platforms; the rest keep working.
  • Relative private_key paths resolve against config.json's directory either way, so moving a platform into config.d/ needs no path edits.
  • No config.d/ directory means no change in behavior.

Read wmt://platforms to see which platforms loaded and what regions and environments they declare. A platform that failed to load has no regions; reading one of its environments returns the loader's own message — which file, which fields, and that a fix needs a restart.

The config is read once at startup. A corrected file needs the server restarted.

Top-level options

FieldDefaultNotes
response_cache_ttl3600Seconds a truncated body or download stays readable at its resource URI
truncate_threshold2048Response bytes returned inline before truncating to a preview

Market → tenant (wap-tenant-id)

Pass tenant on call_endpoint / download_file for non-US walmart:ads markets (e.g. WMT_CA, WMT_MX, WBD_OD). Omit for US and for walmart:marketplace.

Tools

list_endpoints

List operations across every api, with optional filters.

ParameterNotes
queryCase-insensitive substring on operation id, path, or summary
apiLimit to one api, e.g. walmart:marketplace:order-management
platformLimit to one platform — walmart:ads, walmart:marketplace, samsclub:ads (schema enum)
tagFilter by OpenAPI tag
methodFilter by HTTP verb — GET, POST, PUT, PATCH, DELETE (schema enum)

Returned operation ids are qualified (api:operationId) and can be passed straight to describe_endpoint or call_endpoint.

describe_endpoint

One operation plus every components.schemas entry reachable from it, so request bodies can be built without the full spec. Server-managed auth and QoS headers are omitted.

ParameterNotes
operation_idQualified (api:operationId) or bare when unambiguous
apiApi to resolve a bare id in, e.g. walmart:ads:sponsored-products

call_endpoint

Execute an authenticated request against any configured platform.

ParameterNotes
region, environmentRequired. Src: config
operation_idQualified or bare. Resolves api, platform, method, path, and required headers
apiRequired with raw method + path; otherwise inferred from operation_id. Accepts the two auxiliary walmart:ads specs
method, pathRaw route, reaching endpoints absent from the specs
path_paramsValues for {placeholders} in the path
params, bodyQuery string and JSON body
file_pathSend the file as multipart/form-data — Marketplace feed uploads. Pair with the feedType query parameter
advertiser_idRequired on walmart:marketplace, where it selects the credential. Optional on the ads platforms, where it is sent as X-Advertiser-ID
tenantWAP tenant for non-US walmart:ads regions

download_file

Download a report, label, or snapshot from an authenticated endpoint. Give a full url (e.g. the details URL from a display snapshot poll), or operation_id, or api with method + path.

With dest_path the bytes are written there. Without it they are gunzipped when gzipped and cached, and the result carries cached_at — a binary payload with no dest_path asks for one instead. Redirects are followed, keeping auth headers on a relative or same-host Location and dropping credentials cross-host; the result includes urls, the hop path. platform is required only when downloading from a bare url.

refresh_specs

Re-fetch bundled specs into a user cache that then takes precedence over the bundled copies. Pass api to refresh one — e.g. walmart:marketplace:order-management — or omit to refresh all 33, the two auxiliary walmart:ads specs included.

MCP resources

Resource URIDescription
wmt://platformsEvery platform, its auth model, and the regions and environments it declares
wmt://platforms/{platform}/apisThat platform's api ids
wmt://platforms/{platform}/apis/{name}One api: title, version, operation count, and its tags with a count each — the legal list_endpoints(tag=…) values
wmt://platforms/walmart:marketplace/regions/{region}/{environment}/advertisersAdvertiser ids mapped to their Walmart Partner ID (null when unset)
wmt://platforms/{platform}/regions/{region}/{environment}/hostsApi ids mapped to the base URL a call reaches, or * for every api whose host the server owns
wmt://responses/{request_id}Full body of a truncated response or a cached download (in memory, TTL from config)
wmt://curl/{request_id}Reproducible cURL for a previous request, credentials replaced with placeholders

MCP host examples

Cursor

Add to .cursor/mcp.json:

{
  "mcpServers": {
    "walmart": {
      "command": "uvx",
      "args": ["mcp-walmart-ads"]
    }
  }
}

Claude Code

Add to your Claude Code MCP config:

{
  "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"]
    }
  }
}

Where the specs come from

Walmart publishes no OpenAPI files, but each ReadMe reference page hydrates its HTML with the registry UUIDs of its documents, and https://dash.readme.com/api/v1/api-registry/<uuid> serves the full spec unauthenticated. That covers Walmart Connect and all 28 Marketplace domains. Sam's Club publishes neither, so its spec is hand-authored from the developer docs; scripts/build_samsclub_spec.py regenerates a candidate from those docs and the scheduled spec drift workflow opens a PR when they change, as a human review gate. The candidate is never shipped and never loaded at runtime.

Specs are stored verbatim as upstream served them, so a refresh diff shows exactly what changed; oversized inline examples and x-readme metadata are stripped on load rather than on disk.

# Rebuild the bundled specs (registry-sourced 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

Development

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

Contributing

Issues and pull requests are welcome. Please keep changes focused and make sure ruff check, ruff format --check, pyright, and pytest all pass.

License

MIT — see LICENSE.

Installation

Source-derived launch command. Check the maintainer’s required arguments and credentials before running:

bash
uvx mcp-walmart-ads

Set up in your AI client

Merge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.

json
{
  "mcpServers": {
    "io-github-alyiox-mcp-walmart-ads": {
      "command": "uvx",
      "args": [
        "mcp-walmart-ads"
      ]
    }
  }
}

Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.

Claude Desktop setup reference

Package

mcp-walmart-adspypi

Compatible MCP Clients

Walmart & Sam's Club APIs works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.

  • Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.
  • Cursor~/.cursor/mcp.jsonRestart Cursor for changes to take effect.
  • VS Code.vscode/mcp.jsonReload VS Code window for changes to take effect.
  • Windsurf~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect.
  • Claude Code.mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.

Learn More