mcps.portel.dev API Contract
Overview
The NCP CLI now fetches provider information from mcps.portel.dev to enable dynamic, server-side provider registry management. This allows adding new providers without requiring CLI updates.
Base URL
https://mcps.portel.dev/apiEndpoints Required
1. List All Providers
Endpoint: GET /api/providers
Description: Returns all available MCP providers
Response:
{
"canva": {
"id": "canva",
"name": "Canva",
"description": "Design and creative tools",
"website": "https://www.canva.com",
"recommended": "stdio",
"stdio": {
"setup": {
"description": "Authenticate with Canva CLI",
"command": "npx @canva/cli@latest login",
"needsSetup": true
},
"command": "npx",
"args": ["-y", "@canva/cli@latest", "mcp"]
},
"http": {
"url": "https://mcp.canva.com/mcp",
"auth": "oauth",
"docs": "https://www.canva.dev/docs/connect/mcp-server/",
"notes": "Requires OAuth app registration. Stdio version recommended."
}
},
"slack": {
"id": "slack",
"name": "Slack",
...
}
}Alternative Response Format (also supported):
{
"providers": {
"canva": {...},
"slack": {...}
}
}2. Get Single Provider
Endpoint: GET /api/providers/{providerId}
Description: Returns details for a specific provider
Example: GET /api/providers/canva
Response:
{
"id": "canva",
"name": "Canva",
"description": "Design and creative tools",
"website": "https://www.canva.com",
"recommended": "stdio",
"stdio": {
"setup": {
"description": "Authenticate with Canva CLI",
"command": "npx @canva/cli@latest login",
"needsSetup": true
},
"command": "npx",
"args": ["-y", "@canva/cli@latest", "mcp"]
},
"http": {
"url": "https://mcp.canva.com/mcp",
"auth": "oauth",
"docs": "https://www.canva.dev/docs/connect/mcp-server/"
}
}Error Response (404):
{
"error": "Provider not found",
"providerId": "unknown"
}3. Search Providers (Optional)
Endpoint: GET /api/providers/search?q={query}
Description: Search providers by name, description, or ID
Example: GET /api/providers/search?q=design
Response:
{
"results": [
{
"id": "canva",
"name": "Canva",
"description": "Design and creative tools",
...
},
{
"id": "figma",
"name": "Figma",
"description": "Collaborative design tool",
...
}
],
"query": "design",
"count": 2
}Provider Schema
Provider Object
interface Provider {
id: string; // Unique identifier (lowercase)
name: string; // Display name
description: string; // Short description
website: string; // Provider's website
recommended: 'stdio' | 'http'; // Recommended transport
stdio?: ProviderStdioConfig; // Stdio configuration (if available)
http?: ProviderHttpConfig; // HTTP configuration (if available)
}Stdio Configuration
interface ProviderStdioConfig {
setup?: {
description: string; // What the setup does
command: string; // Command to run (e.g., "npx @canva/cli@latest login")
needsSetup: boolean; // Whether setup is required
};
command: string; // Main command (e.g., "npx")
args: string[]; // Arguments (e.g., ["-y", "@canva/cli@latest", "mcp"])
}HTTP Configuration
interface ProviderHttpConfig {
url: string; // MCP endpoint URL
auth: 'bearer' | 'oauth' | 'basic'; // Authentication type
docs: string; // Documentation URL
notes?: string; // Additional notes/warnings
}Client Behavior
Request Flow
User: ncp add canva
↓
1. Fetch: GET https://mcps.portel.dev/api/providers/canva
↓
2. If successful → Use remote provider data
↓
3. If failed (network error, timeout) → Use local fallback
↓
4. Display provider info and guide user through setupTimeouts
- Connection timeout: 5 seconds
- Read timeout: 5 seconds
- On timeout → Use local cache/fallback
Caching
- NCP caches registry in memory during execution
- No persistent cache (always fetches fresh on new command)
- Local
providers.jsonserves as offline fallback
Headers
User-Agent: ncp-cli
Accept: application/jsonError Handling
Server Down
If mcps.portel.dev is unreachable:
- NCP falls back to local
providers.json - User sees:
(Using local provider registry) - Everything continues to work
Provider Not Found
Remote:
{
"error": "Provider not found",
"providerId": "unknown"
}Client behavior:
- Try local fallback
- If still not found → Treat as manual add
- Show:
Unknown provider 'unknown'. Using manual configuration.
Invalid Response
If server returns invalid JSON or unexpected format:
- Log error (if debug mode)
- Fall back to local registry
- Continue operation
Implementation Guidelines for mcps.portel.dev
Performance
- Response time: < 200ms for single provider lookup
- Caching: Implement CDN caching (5-minute TTL recommended)
- Compression: Enable gzip/brotli
Security
- HTTPS only
- CORS: Enable for
ncp-cliUser-Agent - Rate limiting: 100 req/min per IP (generous for CLI tool)
Availability
- Target uptime: 99.9%
- Graceful degradation: If server down, clients use local cache
- Health endpoint:
GET /health→{"status": "ok"}
Data Management
Where providers come from:
- Your existing MCP discovery/submission system
- Manual curation by Portel team
- Community submissions (verified by Portel)
Update frequency:
- Real-time: New providers available immediately
- No CLI update required
- Backward compatible: Old CLIs work with new providers
Integration with Existing Discovery System
Current Flow (Already Working):
User: ncp find "design"
↓
Query: mcps.portel.dev/discover
↓
Found: Canva MCP
↓
Elicitation: Install? (y/n)
↓
Auto-installNew Flow (With Provider Registry):
User: ncp add canva
↓
Query: mcps.portel.dev/api/providers/canva
↓
Get provider details (stdio config, auth setup, etc.)
↓
Guide user through setup
↓
Auto-installUnified Backend
Both endpoints can share the same provider database:
/discover→ Search/discovery API/api/providers→ Provider details API- Same data, different views
Example Provider Entries
Canva (Stdio + HTTP)
{
"id": "canva",
"name": "Canva",
"description": "Design and creative tools",
"website": "https://www.canva.com",
"recommended": "stdio",
"stdio": {
"setup": {
"description": "Authenticate with Canva CLI",
"command": "npx @canva/cli@latest login",
"needsSetup": true
},
"command": "npx",
"args": ["-y", "@canva/cli@latest", "mcp"]
},
"http": {
"url": "https://mcp.canva.com/mcp",
"auth": "oauth",
"docs": "https://www.canva.dev/docs/connect/mcp-server/",
"notes": "Requires OAuth app registration. Stdio version recommended for easier setup."
}
}Notion (HTTP only)
{
"id": "notion",
"name": "Notion",
"description": "Notes and documentation",
"website": "https://notion.so",
"recommended": "http",
"http": {
"url": "https://mcp.notion.so",
"auth": "bearer",
"docs": "https://developers.notion.com/docs/mcp",
"notes": "Requires API key from Notion settings → Integrations → Create integration"
}
}Custom MCP (Community Submitted)
{
"id": "my-custom-mcp",
"name": "My Custom MCP",
"description": "Custom integration for...",
"website": "https://github.com/user/my-mcp",
"recommended": "stdio",
"stdio": {
"command": "node",
"args": ["/path/to/server.js"]
}
}Testing
Endpoint Tests
# Test provider list
curl https://mcps.portel.dev/api/providers
# Test single provider
curl https://mcps.portel.dev/api/providers/canva
# Test not found
curl https://mcps.portel.dev/api/providers/nonexistent
# Should return 404
# Test search
curl "https://mcps.portel.dev/api/providers/search?q=design"CLI Tests
# Test with live server
ncp add canva
# Test with server down (use local fallback)
# Temporarily block mcps.portel.dev in /etc/hosts
ncp add canva # Should still work using local cacheDeployment Checklist
Backend (mcps.portel.dev):
- [ ] Implement
/api/providersendpoint - [ ] Implement
/api/providers/{id}endpoint - [ ] Add provider data (Canva, Slack, GitHub, Notion, Linear)
- [ ] Enable CORS
- [ ] Add rate limiting
- [ ] Deploy to production
- [ ] Test all endpoints
CLI (NCP):
- [ ] Update to fetch from mcps.portel.dev
- [ ] Test remote fetch
- [ ] Test local fallback
- [ ] Build and release
- [ ] Update documentation
Benefits of This Architecture
✅ Dynamic Updates: Add providers without CLI releases ✅ Centralized: Single source of truth ✅ Offline Support: Local fallback if server down ✅ Scalable: Can grow to hundreds of providers ✅ Community: Enable provider submissions ✅ Discovery: Integrate with existing ncp find system
Questions?
Contact: dev@portel.dev Docs: https://docs.portel.dev/api