Prompt
How do I expose SaaS APIs through MCP?
Latest observation
To expose SaaS APIs through MCP (Model Context Protocol), you typically build an MCP server that acts as a thin, controlled adapter between the model and your SaaS backend.
High-level idea
MCP lets an LLM client discover and call:
- tools: actions/functions like
create_ticket,search_customers - resources: read-only data like
customer://123 - prompts: reusable prompt templates
For a SaaS API, the most common pattern is:
- Map REST/GraphQL endpoints to MCP tools
- Validate inputs and enforce auth/permissions
- Translate MCP calls into API requests
- Return concise, structured results
Typical architecture
LLM client → MCP server → Your SaaS API
The MCP server usually handles:
- Authentication to your SaaS
- Tenant isolation
- Input validation
- Rate limiting
- Output shaping/redaction
- Tool discovery and documentation
Step-by-step approach
1) Decide what to expose
Don’t expose every internal endpoint. Pick a small set of safe, useful operations.
Good candidates:
- Search/list
- Get details
- Create/update common objects
- Workflow actions
Avoid or tightly control:
- Destructive actions
- Bulk exports
- Admin-only endpoints
- Anything requiring complex multi-step confirmation
2) Design MCP tools around user intent
Instead of mirroring raw REST endpoints, create task-oriented tools.
For example, instead of:
POST /v1/customersGET /v1/customers/{id}GET /v1/customers?query=...
Expose:
search_customersget_customercreate_customer
This makes the model much better at using them.
Example tool schema:
{
"name": "search_customers",
"description": "Search customers by name, email, or company.",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" },
"limit": { "type": "integer", "default": 10 }
},
"required": ["query"]
}
}
3) Implement the MCP server
You can build it in Node.js, Python, or any language that supports MCP transport and JSON-RPC style handling.
Your server should:
- Advertise tools via MCP
- Accept tool calls
- Call your SaaS API with service credentials or user-delegated tokens
- Return structured JSON
4) Handle auth properly
This is one of the most important parts.
You generally have two patterns:
A. Server-side credential
The MCP server uses its own service account to talk to your SaaS.
Use this when:
- All calls are under a single workspace
- You control the environment
- You can safely scope permissions
B. User-delegated OAuth/token
Each user connects their SaaS account.
Use this when:
- Actions should reflect the user’s permissions
- You need tenant/user-level access control
- You’re exposing customer-specific data
Best practice:
- Map MCP session identity to SaaS tenant/user identity
- Enforce authorization in the MCP server, not just in the model
5) Return model-friendly output
Keep responses:
- Short
- Structured
- Clear
- Free of unnecessary noise
Example response:
{
"customers": [
{
"id": "cus_123",
"name": "Acme Corp",
"email": "billing@acme.com",
"status": "active"
}
]
}
Avoid returning:
- Huge raw payloads
- Internal debug metadata
- Sensitive fields unless explicitly needed
6) Add resource endpoints when useful
If your SaaS has read-only objects that are often referenced, expose them as MCP resources.
Example:
customer://cus_123invoice://inv_456
This works well for:
- Loading object details
- Referencing entities in conversations
- Letting clients inspect data on demand
7) Add prompts for common workflows
You can provide prompts like:
- “Summarize this customer account”
- “Prepare a renewal email”
- “Draft a support reply using ticket context”
This is optional, but useful if your SaaS has common workflows.
Practical design tips
Keep tools atomic
One tool should do one thing well.
Bad:
manage_customer_and_invoices_and_support
Good:
create_customerlist_invoicesget_support_ticket
Use strong schemas
Make required fields explicit. Add enums where possible. This reduces hallucinated arguments.
Prefer stable IDs
Use your internal object IDs rather than names alone.
Sanitize outputs
Strip secrets, tokens, internal notes, private fields, and PII unless necessary.
Paginate everything
Search/list tools should support:
limitcursororoffset
Include clear descriptions
Tool descriptions should explain:
- What it does
- When to use it
- Any side effects
Example mapping
SaaS endpoint
GET /v1/projects?org_id=...
MCP tool
list_projects
Input:
{ "organization_id": "org_123", "limit": 20 }
Output:
{
"projects": [
{ "id": "prj_1", "name": "Website Redesign", "status": "active" }
]
}
Security checklist
Before exposing SaaS APIs through MCP, make sure you have:
- Authentication on every tool
- Authorization checks per tenant/user
- Input validation
- Rate limits
- Logging/auditing
- Output redaction
- Confirmation for destructive actions
- Isolation between customers
- Safe defaults and least privilege
Recommended rollout strategy
- Start with read-only tools
- Add search and retrieval
- Add low-risk write actions
- Add sensitive/destructive actions only with confirmations
- Monitor usage and failures
- Tighten schemas and permissions based on real usage
If you’re building for external developers
Consider offering:
- A public MCP server
- Developer docs for available tools
- OAuth flow for user connection
- Versioning for tools/schemas
- Sandbox environment
Minimal example in concept
If your SaaS has an endpoint:
GET /customers/search?q=acme
Your MCP tool might:
- accept
{ "query": "acme" } - call the API
- return top matches
The MCP server becomes a safe, structured wrapper around your API.
If you want, I can also show you:
- a Node.js MCP server example for a SaaS API,
- a Python example, or
- a recommended tool design pattern for your specific API.