Building MCP Servers
Advanced guide for developers building their own MCP servers that authenticate against Whatalo using OAuth 2.1.
This is an advanced guide for developers building their own MCP servers (Model Context Protocol) that authenticate against Whatalo's API on behalf of a merchant.
Most integrators do not need this. If you want to connect an AI tool to a Whatalo store, use the existing Whatalo MCP server instead — see Connecting your store to AI tools. This page is only for developers building a new MCP server of their own.
Audience: MCP server authors and third-party developers building OAuth-based resource servers for Whatalo.
Architecture
There are three principals in every MCP + Whatalo integration:
| Role | Who | Identifier |
|---|---|---|
| Authorization Server | Whatalo | app.whatalo.com |
| Resource Server | Your MCP server | Receives Bearer tokens, validates via introspection |
| OAuth Client | MCP host application | Gets a client_id via Dynamic Client Registration |
┌─────────────────────┐ ┌──────────────────────┐ ┌───────────────────┐
│ MCP Host App │ │ Whatalo Auth Server │ │ Your MCP Server │
│ (OAuth Client) │ │ (app.whatalo.com) │ │ (Resource Server)│
└──────────┬──────────┘ └──────────┬────────────┘ └─────────┬─────────┘
│ │ │
│ 1. DCR: POST /oauth/register │
├──────────────────────────►│ │
│ ◄── client_id ───────────│ │
│ │ │
│ 2. Authorization Code + PKCE │
├──────────────────────────►│ │
│ ◄── access + refresh ────│ │
│ │ │
│ 3. MCP request with Bearer token │
├─────────────────────────────────────────────────────► │
│ │ 4. Introspect token │
│ │◄────────────────────────────┤
│ ├──── { active, sub, scope } ►│
│ ◄── MCP response ──────────────────────────────────────┤Key point: your MCP server is a Resource Server, not an OAuth client. The MCP host application running on the user's machine is the OAuth client. This is the single most common mistake when combining MCP and OAuth — do not register your server as the client.
OAuth flow — reuse the canonical reference
Your MCP server relies on Whatalo's standard OAuth 2.1 endpoints. Each step is documented once, in the OAuth section — follow those pages rather than a duplicated copy:
| Step | Reference |
|---|---|
| Authorization Server metadata | Discovery |
| Dynamic Client Registration | Registration |
| Authorization Code + PKCE | Authorization Flow |
| Exchanging the code for tokens | Token Endpoint |
| Refreshing tokens | Token Exchange |
| Validating Bearer tokens | Introspection |
| Revoking tokens | Revocation |
| Available scopes | Scopes |
| Error format | Errors |
Resource Server discovery
Your MCP server must publish OAuth Protected Resource metadata (RFC 9728) so that MCP host applications can discover Whatalo as the authorization server:
GET https://YOUR_MCP_DOMAIN/.well-known/oauth-protected-resourceResponse:
{
"resource": "https://YOUR_MCP_DOMAIN",
"authorization_servers": ["https://app.whatalo.com"],
"scopes_supported": [
"read:store",
"read:products",
"write:products",
"read:inventory",
"write:inventory",
"read:categories",
"write:categories",
"read:customers",
"read:orders",
"write:orders"
],
"bearer_methods_supported": ["header"]
}The authorization_servers array pointing to https://app.whatalo.com is what ties your MCP server to Whatalo as the authorization server. Only advertise the scopes your server actually enforces.
Routing requests to the right store
When you validate an incoming Bearer token via introspection, the active-token response includes a whatalo_store_id field:
{
"active": true,
"scope": "read:products read:orders",
"sub": "usr_7f3a9b2c1d4e5f6a",
"whatalo_store_id": "str_8k2m4n6p"
}The whatalo_store_id field contains the store's public short ID — the same one used in Whatalo URLs. Use it to route operations to the correct store context in your multitenant MCP server. A merchant with multiple stores authorizes each store separately, so each token resolves to exactly one store.
Security checklist
- ✅ Always use PKCE with
S256— neverplain - ✅ Validate the
stateparameter on every callback - ✅ Store tokens in OS keychain or encrypted storage — never
localStorage - ✅ Cache
active: trueintrospection responses for at most 60 seconds — revocations are immediate - ✅ Request only the minimum scopes you need
- ❌ Never log raw tokens or send them in URL query strings
References
- RFC 9728 — OAuth Protected Resource Metadata
- RFC 7662 — Token Introspection
- MCP Authorization Specification — Model Context Protocol