Skip to main content

Architecture

Code structure, transport layers, core modules, request flow, and security design of the WooCommerce MCP Server.

Project Structure

woocommerce-mcp-server/
├── src/
│ ├── index.ts # Stdio entry point (local MCP clients)
│ ├── http.ts # HTTP/Express entry point (remote access)
│ ├── lambda.ts # AWS Lambda handler (serverless)
│ ├── server.ts # Shared server factory and request routing
│ ├── sanitize.ts # Product data sanitization layer
│ ├── types.ts # Shared TypeScript types
│ ├── middleware/
│ │ └── auth.ts # API key validation middleware
│ └── tools/
│ ├── publicTools.ts # 4 sanitized read-only product tools
│ └── privateTools.ts # All 159+ tools (full access)
├── build/ # Compiled JavaScript output
├── package.json # ESM project configuration
├── tsconfig.json # TypeScript compiler settings
└── deploy-package.ps1 # Lambda deployment packaging script

Entry Points

The server supports two primary transport modes, each with its own entry point:

Stdio Transport (src/index.ts)

Used by local MCP clients (VS Code, PhpStorm, Claude Desktop) that spawn the server as a child process.

IDE → spawns process → node build/index.js
← stdin/stdout JSON-RPC messages →
  • Creates a "full" MCP server instance with all 159+ tools registered
  • Uses StdioServerTransport from the MCP SDK
  • No authentication required (the spawning process owns the connection)
  • All tools return unsanitized data

HTTP Transport (src/http.ts)

Used for remote access, Docker deployments, or REST-based integrations.

Client → HTTPS POST → Express → MCP Server
← JSON-RPC response ←
  • Exposes three endpoints: /health, /mcp (public), /mcp/admin (authenticated)
  • Uses StreamableHTTPServerTransport in stateless mode
  • Public endpoint registers only 4 sanitized product tools
  • Admin endpoint registers all 159+ tools with full data access
  • Each request creates a fresh transport (stateless — no session persistence)

Core Modules

server.ts — Server Factory

The central module that creates configured MCP server instances:

  • createMcpServer(mode) — Factory function that returns an MCP server configured for either "public" (4 tools) or "full" (159+ tools) mode
  • handleWooCommerceRequest() — Translates MCP tool calls into WooCommerce REST API requests using Axios
  • Zod Schemas — Runtime validation for credentials, pagination parameters, and tool inputs
  • Credential Resolution — Reads environment variables and validates required fields at startup

sanitize.ts — Data Sanitization

Strips sensitive information from product responses on the public endpoint:

Exact Keys Removed (19): Cost prices, stock quantities, purchase notes, internal SKU mappings, and plugin-specific metadata fields that could expose business logic or pricing strategies.

Prefix Patterns Removed (7): Any metadata key starting with known plugin prefixes (e.g., _wc_, _sku_, internal tracking prefixes) is automatically stripped.

This ensures the public endpoint exposes only customer-facing product information — names, descriptions, prices, images, and categories — without leaking internal data.

middleware/auth.ts — API Key Validation

Protects the /mcp/admin endpoint:

  • Reads the Authorization: Bearer <token> header
  • Compares against the MCP_API_KEY environment variable
  • Uses crypto.timingSafeEqual for constant-time comparison (prevents timing attacks)
  • Returns 401 Unauthorized if the key is missing or invalid

tools/publicTools.ts — Public Tool Definitions

Registers 4 read-only product tools for the public endpoint:

ToolDescription
get_productsList products with pagination and filtering
get_productGet a single product by ID
get_product_detailsGet detailed product information
search_productsSearch products by keyword, category, tag, or price range

All responses pass through the sanitization layer before being returned.

tools/privateTools.ts — Full Tool Definitions

Registers all 159+ tools organized by domain. Each tool definition includes:

  • Name — Unique identifier (e.g., get_orders, create_product)
  • Description — Human-readable explanation for the AI assistant
  • Input Schema — Zod schema defining required and optional parameters
  • Handler — Function that calls handleWooCommerceRequest() with the appropriate REST API endpoint and method

Request Flow

Stdio Mode (IDE Usage)

1. IDE spawns: node build/index.js (with env vars)
2. Server initializes → registers all 159+ tools
3. IDE sends JSON-RPC: {"method": "tools/list"} via stdin
4. Server responds with tool catalog via stdout
5. AI decides to call a tool (e.g., get_orders)
6. IDE sends: {"method": "tools/call", "params": {"name": "get_orders", ...}}
7. Server calls WooCommerce REST API: GET /wp-json/wc/v3/orders
8. WooCommerce responds with order data
9. Server formats and returns result via stdout
10. AI uses the data to generate a response

HTTP Mode (Remote Access)

1. Server starts: node build/http.js (Express on port 3000)
2. Client sends POST /mcp/admin with Authorization header
3. Auth middleware validates API key (constant-time comparison)
4. Fresh StreamableHTTPServerTransport created for request
5. JSON-RPC body parsed → tool call dispatched
6. Server calls WooCommerce REST API
7. Response returned as JSON-RPC result
8. Transport is destroyed (stateless)

Security Design

Authentication Layers

LayerMechanismProtects
HTTP Admin EndpointBearer token + crypto.timingSafeEqual/mcp/admin from unauthorized access
WooCommerce APIConsumer Key + Consumer Secret (HMAC)WordPress REST API endpoints
WordPress PostsUsername + Application Password (Basic Auth)Post/meta CRUD operations

Data Isolation

  • Public endpoint (/mcp): 4 tools, sanitized responses, no authentication
  • Admin endpoint (/mcp/admin): 159+ tools, full responses, API key required
  • Stdio mode: All tools, full responses, no auth (trusted local process)

Credential Management

  • All credentials are provided via environment variables
  • Never hardcoded in source code
  • IDE configurations store credentials locally (never committed to version control)
  • Per-request credential override is supported for multi-store scenarios

Self-Signed Certificate Handling

When ALLOW_SELF_SIGNED_CERTS=true:

  • Sets NODE_TLS_REJECT_UNAUTHORIZED=0 for the process
  • Configures Axios to accept self-signed certificates
  • Only for local development — production deployments must use valid SSL certificates

Technology Decisions

DecisionRationale
ESM (ES Modules)Modern Node.js standard, better tree-shaking, required by MCP SDK
Zod v4Runtime validation with TypeScript type inference, lightweight
ExpressMature HTTP framework with middleware ecosystem
AxiosRobust HTTP client with interceptors, retry support, and proxy configuration
Stateless HTTP TransportEach request is independent — no session state to manage, suitable for serverless
Constant-time auth comparisonPrevents timing side-channel attacks on API key validation

Build System

TypeScript Configuration

{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"esModuleInterop": true,
"strict": true,
"outDir": "build",
"skipLibCheck": true
}
}

Key settings:

  • ES2022 target — Modern JavaScript features without polyfills
  • Node16 module resolution — Proper ESM support with .js extensions in imports
  • Strict mode — Full type checking enabled

NPM Scripts

ScriptCommandPurpose
buildtscCompile TypeScript to JavaScript
startnode build/index.jsRun in stdio mode
start:httpnode build/http.jsRun in HTTP mode

Next Steps