MCP server for SkinGuide: search skincare products by Baumann skin type, product category, budget, and ingredients. Exposes AI-friendly endpoints for dry, oily, sensitive, and all other skin types.
| Website | skinguide.beauty |
| GitHub | robertozerbini/skinguide-mcp-server |
| Protocol | Model Context Protocol 2024-11-05 |
| Transports | stdio (npx) |
- Overview
- Tools
- Repository Structure
- Quick Start
- Environment Variables
- Tool Reference and Examples
- Baumann Skin Type System
- AI Agent Integration
- Direct API Usage (Python)
- Google Colab Notebook
- Example Clients
- API Discovery
- Contributing
- License
SkinGuide MCP Server implements the Model Context Protocol to expose skincare product search and skin type information as structured AI tools.
AI agents, LLM applications, and developer tools can:
- Discover all 16 Baumann skin types and their characteristics
- Search a curated skincare product catalogue filtered by skin type, category, budget, ingredients, and keywords
- Recommend personalised routines based on Baumann axes (O/D, S/R, P/N, W/T)
| Tool | Description |
|---|---|
search_products |
Search products by skin type, brand, category, budget, keyword, and ingredient |
get_skin_type_info |
Detailed info for a Baumann skin type code |
list_skin_types |
All 16 Baumann codes with names, categories, and descriptions |
get_product_types |
All available product categories |
get_routine |
Step-by-step skincare routine for a Baumann skin type (AM/PM, gender) |
get_brands |
All available brands in the database |
skinguide-mcp-server/
├── Dockerfile # Optional containerized runtime
├── src/
│ ├── index.ts # MCP stdio entry-point (TypeScript)
│ ├── tools.ts # Tool handlers + live API proxy
│ └── types.ts # Shared interfaces/types
├── dist/ # Compiled output (generated)
├── package.json
├── tsconfig.json
├── examples/
│ ├── blogcreation.ipynb # Colab notebook: autonomous blog-writing agent
│ ├── direct_api_client.py
│ ├── node_client.js # Node.js demo (built-in fetch)
│ └── python_client.py # Python MCP stdio demo
└── .well-known/
└── mcp.json # MCP discovery document
npm install
npm startNo installation required. The MCP server runs on-demand via npx and fetches live product data from https://skinguide.beauty/api/products.
docker build -t skinguide-mcp .
docker run -i --rm skinguide-mcpEdit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"skinguide": {
"command": "npx",
"args": ["skinguide-mcp-server"]
}
}
}Edit .cursor/mcp.json:
{
"mcpServers": {
"skinguide": {
"command": "npx",
"args": ["skinguide-mcp-server"]
}
}
}Edit .vscode/mcp.json:
{
"servers": {
"skinguide": {
"type": "stdio",
"command": "node",
"args": ["dist/index.js"]
}
}
}curl https://skinguide.beauty/.well-known/mcp.json| Variable | Default | Description |
|---|---|---|
LIVE_API_URL |
https://skinguide.beauty/api |
Base URL for the live SkinGuide API |
All tools are invoked by the MCP client (Claude, Cursor, VS Code) over stdio. The JSON-RPC 2.0 envelope used internally:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "<tool_name>",
"arguments": {}
}
}List all 16 Baumann skin types. Input: none.
Response excerpt:
{
"skinTypes": [
{
"code": "DSPW",
"name": "Dry, Sensitive, Pigmented, Wrinkled",
"category": "dry-sensitive",
"difficulty": 5,
"description": "The most complex skin type. Needs rich hydration, anti-inflammatory care, brightening, and anti-aging support simultaneously."
},
{
"code": "DSNW",
"name": "Dry, Sensitive, Non-pigmented, Wrinkled",
"category": "dry-sensitive",
"difficulty": 4,
"description": "Dry and sensitive with visible aging but even tone. Prioritise deep hydration, barrier repair, and anti-aging actives."
}
],
"total": 16
}(14 more types omitted — all 16 returned in the real response)
List all available product categories. Input: none.
{
"productTypes": [
{ "id": "Cleanser" },
{ "id": "Moisturizer" },
{ "id": "Serum" },
{ "id": "Sunscreen" },
{ "id": "Toner" },
{ "id": "Eye Cream" },
{ "id": "Face Mask" },
{ "id": "Exfoliator" },
{ "id": "Face Oil" },
{ "id": "Treatment" }
],
"total": 10
}Input: skinType (string, required) — 4-letter Baumann code, e.g. OSPT, DRNT, DSPW.
Response:
{
"code": "OSPT",
"name": "Oily, Sensitive, Pigmented, Tight",
"category": "oily-sensitive",
"difficulty": 4,
"description": "Very common in teens and young adults. Oily, acne-prone, and sensitive with post-inflammatory dark spots."
}Input parameters:
| Parameter | Type | Description |
|---|---|---|
type |
string | Product category: Cleanser, Moisturizer, Serum, Sunscreen, Toner, Eye Cream, Face Mask, Exfoliator, Face Oil, Treatment |
skinType |
string | Direct 4-letter Baumann code, e.g. OSPT. Alternative to using axes individually. |
od |
"O" or "D" | Oily or Dry axis |
sr |
"S" or "R" | Sensitive or Resistant axis |
pn |
"P" or "N" | Pigmented or Non-pigmented axis |
wt |
"W" or "T" | Wrinkled or Tight axis |
brand |
string | Filter by brand name (partial match, case-insensitive). E.g. CeraVe, La Roche. |
keyword |
string | Search keyword matched against product name (case-insensitive). E.g. acne, anti-aging. |
ingredient |
string | Filter by ingredient (partial match, case-insensitive). E.g. retinol, hyaluronic acid. |
budget |
number | Maximum price in dollars (use 5, 10, 20, 50, 100, or 101 for over $100) |
limit |
integer | Max results, 1–50 (default 50) |
Example — oily + sensitive skin (od=O, sr=S), budget $30:
Arguments:
{ "od": "O", "sr": "S", "budget": 30, "limit": 5 }Example — search by direct skin type and ingredient:
{ "skinType": "OSPT", "ingredient": "niacinamide", "limit": 10 }Response:
{
"total": 5,
"query": { "type": "all", "skinType": null, "od": "O", "sr": "S", "pn": null, "wt": null, "budget": 30, "keyword": null, "ingredient": null },
"products": [
{
"id": 534,
"name": "Persa-Gel 10 Oil-Free Acne Spot Treatment",
"brand": "Clean & Clear",
"type": "Treatment",
"price": 5.97,
"currency": "$",
"vegan": false,
"ingredients": ["Benzoyl Peroxide 10%"],
"image": "https://m.media-amazon.com/images/I/612wW4IikOL._AC_UL320_.jpg",
"link": "https://amzn.to/4aTFj3m",
"country": "US",
"skinTypes": ["OSPT"]
}
]
}Get the step-by-step skincare routine for a Baumann skin type.
Input parameters:
| Parameter | Type | Description |
|---|---|---|
skinType |
string, required | 4-letter Baumann code, e.g. OSPT |
gender |
"male" or "female" | Optional — filter steps by gender |
timeOfDay |
"AM" or "PM" | Optional — filter to morning or evening steps |
Example — AM routine for OSPT:
{ "skinType": "OSPT", "timeOfDay": "AM" }Response:
{
"skinType": "OSPT",
"total": 4,
"steps": [
{ "step": 1, "productType": "Cleanser", "action": "Cleanse", "timeOfDay": "AM" },
{ "step": 2, "productType": "Toner", "action": "Tone", "timeOfDay": "AM" },
{ "step": 3, "productType": "Serum", "action": "Apply serum", "timeOfDay": "AM" },
{ "step": 4, "productType": "Sunscreen", "action": "Apply sunscreen", "timeOfDay": "AM" }
]
}Get all available skincare brands in the database. Input: none.
Response:
{
"total": 42,
"brands": [
"Acure",
"Biossance",
"CeraVe",
"Clean & Clear",
"La Roche-Posay",
"Neutrogena"
]
}
⚠️ This tool is available in the server but is not exposed in the current MCP discovery document. It can be re-enabled by adding it back to.well-known/mcp.jsonandsrc/index.ts.
Get illustration image URL(s) for a Baumann skin type. Returns portrait images (hosted on Firebase Storage) representing the skin type across different ethnicities.
Input parameters:
| Parameter | Type | Description |
|---|---|---|
skinType |
string, required | 4-letter Baumann code, e.g. OSPT |
race |
"Asian", "Black", "Latin", or "White" | Optional — filter to a specific ethnicity. Omit for all four. |
The Baumann Skin Type Indicator (BSTI) classifies skin along four binary axes:
| Axis | Options | Meaning |
|---|---|---|
| O/D | O = Oily, D = Dry | Sebum production |
| S/R | S = Sensitive, R = Resistant | Skin reactivity |
| P/N | P = Pigmented, N = Non-pigmented | Pigmentation tendency |
| W/T | W = Wrinkled, T = Tight | Aging / wrinkle tendency |
Combined: 16 unique types (DRNT = easiest, DSPW = most complex).
| Code | Name | Category | Difficulty |
|---|---|---|---|
| DRNT | Dry, Resistant, Non-pigmented, Tight | dry-resistant | 1 |
| DRNW | Dry, Resistant, Non-pigmented, Wrinkled | dry-resistant | 2 |
| DRPT | Dry, Resistant, Pigmented, Tight | dry-resistant | 2 |
| DRPW | Dry, Resistant, Pigmented, Wrinkled | dry-resistant | 3 |
| DSNT | Dry, Sensitive, Non-pigmented, Tight | dry-sensitive | 2 |
| DSNW | Dry, Sensitive, Non-pigmented, Wrinkled | dry-sensitive | 4 |
| DSPT | Dry, Sensitive, Pigmented, Tight | dry-sensitive | 3 |
| DSPW | Dry, Sensitive, Pigmented, Wrinkled | dry-sensitive | 5 |
| ORNT | Oily, Resistant, Non-pigmented, Tight | oily-resistant | 1 |
| ORNW | Oily, Resistant, Non-pigmented, Wrinkled | oily-resistant | 2 |
| ORPT | Oily, Resistant, Pigmented, Tight | oily-resistant | 2 |
| ORPW | Oily, Resistant, Pigmented, Wrinkled | oily-resistant | 3 |
| OSNT | Oily, Sensitive, Non-pigmented, Tight | oily-sensitive | 3 |
| OSNW | Oily, Sensitive, Non-pigmented, Wrinkled | oily-sensitive | 4 |
| OSPT | Oily, Sensitive, Pigmented, Tight | oily-sensitive | 4 |
| OSPW | Oily, Sensitive, Pigmented, Wrinkled | oily-sensitive | 5 |
The MCP server communicates over stdio and works with any AI client that supports MCP. Configure it as shown in the Quick Start section above.
For a deeper look at the JSON-RPC 2.0 request/response format used over the wire, see the demo clients in the examples/ directory.
A Jupyter notebook demonstrating an AI agent that writes blog posts using SkinGuide:
examples/blogcreation.ipynb
Features:
- Runs natively in Google Colab
- Uses LangChain + LangGraph to create an autonomous agent
- Bridges MCP server stdio with OpenAI GPT-4o for real-time product research
- Generates Markdown blog posts with real skincare recommendations
Usage:
- Open the notebook in Google Colab
- Add your
OPENAI_API_KEYto Colab Secrets - Clone/mount the repo and run cells sequentially
- Modify the
user_topicvariable to generate custom blog posts
You can also call the live API directly without the MCP server. The API accepts POST requests with JSON payload:
import requests
import json
url = "https://skinguide.beauty/api/products"
payload = {
"type": "Moisturizer Day",
"od": "D", # Dry
"sr": "S", # Sensitive
"budget": 20,
"country": "US",
"limit": 20
}
response = requests.post(url, json=payload)
print("Status Code:", response.status_code)
print("Response:", json.dumps(response.json(), indent=2))Supported parameters:
| Parameter | Type | Description |
|---|---|---|
type |
string | Product category (see get_product_types for full list) |
country |
"US" or "UAE" |
Country for product availability |
od |
"O" or "D" |
Oily or Dry |
sr |
"S" or "R" |
Sensitive or Resistant |
pn |
"P" or "N" |
Pigmented or Non-pigmented |
wt |
"W" or "T" |
Wrinkled or Tight |
budget |
number | Maximum price in dollars (5, 10, 20, 50, 100, or 101 for over $100) |
limit |
number | Maximum number of results (default 50) |
Three demo clients are included in the examples/ directory:
# Direct API client (stdlib only — no Node.js required, works in Colab)
python3 examples/direct_api_client.py
# MCP stdio clients (require Node.js + npm install)
node examples/node_client.js
python3 examples/python_client.pyGET https://skinguide.beauty/.well-known/mcp.json
The document describes server name, version, URL, transport options, and all tools with full JSON Schema input/output definitions — ready for AI agent auto-discovery.
- Fork the repo
- Create a feature branch:
git checkout -b feat/my-feature - Commit:
git commit -m 'feat: add my feature' - Push and open a PR
Please follow Conventional Commits.
MIT — © SkinGuide · skinguide.beauty