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
StdioServerTransportfrom 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
StreamableHTTPServerTransportin 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) modehandleWooCommerceRequest()— 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_KEYenvironment variable - Uses
crypto.timingSafeEqualfor 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:
| Tool | Description |
|---|---|
get_products | List products with pagination and filtering |
get_product | Get a single product by ID |
get_product_details | Get detailed product information |
search_products | Search 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
| Layer | Mechanism | Protects |
|---|---|---|
| HTTP Admin Endpoint | Bearer token + crypto.timingSafeEqual | /mcp/admin from unauthorized access |
| WooCommerce API | Consumer Key + Consumer Secret (HMAC) | WordPress REST API endpoints |
| WordPress Posts | Username + 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=0for the process - Configures Axios to accept self-signed certificates
- Only for local development — production deployments must use valid SSL certificates
Technology Decisions
| Decision | Rationale |
|---|---|
| ESM (ES Modules) | Modern Node.js standard, better tree-shaking, required by MCP SDK |
| Zod v4 | Runtime validation with TypeScript type inference, lightweight |
| Express | Mature HTTP framework with middleware ecosystem |
| Axios | Robust HTTP client with interceptors, retry support, and proxy configuration |
| Stateless HTTP Transport | Each request is independent — no session state to manage, suitable for serverless |
| Constant-time auth comparison | Prevents 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
.jsextensions in imports - Strict mode — Full type checking enabled
NPM Scripts
| Script | Command | Purpose |
|---|---|---|
build | tsc | Compile TypeScript to JavaScript |
start | node build/index.js | Run in stdio mode |
start:http | node build/http.js | Run in HTTP mode |
Next Steps
- Tools Reference — Complete catalog of all 159+ available tools organized by category
- Installation — Build and run the server
- IDE Configuration — Connect your IDE to the server