Authentication Guide
NCP supports authentication for MCPs that require API keys, tokens, or credentials. This guide shows you how to provide credentials non-interactively.
Quick Reference
# HTTP MCP with bearer token
ncp add https://mcp.example.com --token "your-token-here"
# Registry-based HTTP MCP with token
ncp add notion --token "secret_xxx"
# stdio MCP with environment variables
ncp add github --env GITHUB_TOKEN=ghp_xxx
# stdio MCP with auto-setup (interactive)
ncp add github -yHTTP MCPs (Bearer Tokens)
Most HTTP/SSE MCPs use bearer token authentication.
From Registry
# Add with token in one command
ncp add canva --token "your-canva-token"
# Registry auto-detects that Canva uses HTTP transport
# Token is saved to your profile configurationManual HTTP URLs
# Direct URL with token
ncp add https://mcp.example.com --token "bearer_xxx"
# NCP auto-detects this is an HTTP endpoint
# Generates name from domain: "mcp-example-com"Without Token (Manual Config Required)
# Add without token - will warn
ncp add notion
# Output:
# ⚠️ Bearer token required but not provided
# Add token later: ncp add notion --token "your-token"To add token later:
ncp add notion --token "your-token-here"
# This overwrites the existing configurationstdio MCPs (Environment Variables)
stdio MCPs often need API keys or credentials as environment variables.
Using --env Flag
# Single environment variable
ncp add github --env GITHUB_TOKEN=ghp_xxxxxxxxxxxx
# Multiple environment variables
ncp add slack \
--env SLACK_BOT_TOKEN=xoxb-xxx \
--env SLACK_TEAM_ID=T123456
# Complex values (use quotes)
ncp add postgres \
--env POSTGRES_CONNECTION_STRING="postgresql://user:pass@host:5432/db"Using Setup Commands (Interactive)
Some MCPs have setup commands that handle authentication for you.
# Auto-run setup with -y flag
ncp add github -y
# This runs: gh auth login
# Opens browser for OAuth authenticationWithout -y flag:
ncp add github
# Prompts:
# Run authentication now? (y/n):Common Patterns
GitHub
Option 1: Personal Access Token
# Non-interactive
ncp add github --env GITHUB_TOKEN=ghp_xxxxxxxxxxxxOption 2: OAuth via GitHub CLI
# Interactive
ncp add github -y
# Opens browser for authenticationSlack
ncp add slack \
--env SLACK_BOT_TOKEN=xoxb-xxxxxxxxxxxx \
--env SLACK_TEAM_ID=T01234567Notion
ncp add notion --token "secret_xxxxxxxxxxxx"OpenAI
ncp add openai --env OPENAI_API_KEY=sk-xxxxxxxxxxxxPostgreSQL
ncp add postgres \
--env POSTGRES_CONNECTION_STRING="postgresql://user:pass@localhost:5432/mydb"Security Best Practices
1. Never Commit Tokens to Git
# Add to .gitignore
echo "*.token" >> .gitignore
echo ".env" >> .gitignore2. Use Environment Variables in CI/CD
# GitHub Actions example
ncp add github --env GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
# Shell script
ncp add notion --token "$NOTION_TOKEN"3. Store Tokens Securely
# Use a secrets file with restrictive permissions
echo "your-token" > ~/.secrets/notion_token
chmod 600 ~/.secrets/notion_token
# Read from file
ncp add notion --token "$(cat ~/.secrets/notion_token)"4. Rotate Tokens Regularly
# Generate new token on provider's website
# Update in NCP
ncp add notion --token "new-token-here" # Overwrites old token5. Secure NCP Profiles
# Restrict permissions on profile directory
chmod 700 ~/.ncp
chmod 600 ~/.ncp/profiles/*.jsonWhere Credentials Are Stored
Location: ~/.ncp/profiles/<profile>.json
Format:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"
}
},
"notion": {
"url": "https://mcp.notion.so",
"auth": {
"type": "bearer",
"token": "secret_xxxxxxxxxxxx"
}
}
}
}Security Notes:
- Stored in plain text (secure your home directory)
- Never sent to Portel servers
- Only read by NCP when connecting to MCPs
Updating Credentials
Update Token
# Re-run add command with new token
ncp add notion --token "new-token-here"Update Environment Variables
# Re-run add command with new values
ncp add github --env GITHUB_TOKEN=ghp_new_token_hereManual Edit
# Find config location
ncp config location
# Edit manually
code ~/.ncp/profiles/all.jsonTroubleshooting
"Authentication failed" Error
Check token validity:
- Generate new token on provider's website
- Verify token has correct scopes/permissions
- Re-add with new token:
ncp add <name> --token "new-token"
"Permission denied" Error
Check environment variables:
# Verify environment variable format
ncp add github --env GITHUB_TOKEN=ghp_xxx
# Check token has required permissions
# (e.g., GitHub tokens need 'repo' scope for private repos)Token Keeps Expiring
Solutions:
Use stdio with OAuth: Provider CLI handles token refresh
bashncp add github -y # Uses gh CLI, handles refresh automaticallyGenerate longer-lived tokens: Check provider settings for token expiration
Use manual refresh: Re-run add command when token expires
Can't Find How to Generate Token
Steps:
- Visit provider's website (e.g., github.com, notion.so)
- Go to Settings → Developer Settings → Personal Access Tokens
- Generate new token with required scopes
- Copy token immediately (won't be shown again)
- Use with NCP:
ncp add <provider> --token "token-here"
Common locations:
- GitHub: Settings → Developer settings → Personal access tokens
- GitLab: Preferences → Access Tokens
- Slack: api.slack.com → Your Apps → OAuth & Permissions
- Notion: notion.so/my-integrations
stdio vs HTTP: Which to Use?
Prefer stdio When Available
Advantages:
- Provider handles authentication
- Automatic token refresh
- One-time setup (via
-yflag or--env)
Example:
# GitHub offers both stdio and HTTP
# stdio version is easier:
ncp add github -y # OAuth via gh CLI
# vs HTTP version:
ncp add github --transport http --token "ghp_xxx" # Manual tokenUse HTTP When
- Provider only offers HTTP endpoint
- You prefer manual token control
- stdio version has issues
Example:
# Notion only offers HTTP
ncp add notion --token "secret_xxx"Advanced: OAuth (Coming Soon)
We're building OAuth proxy support to simplify authentication:
- No manual token generation needed
- Browser-based authentication flow
- Tokens stay local (never stored by Portel)
- Support for 50+ providers
Status: In development Updates: https://github.com/portel-dev/oauth-proxy
For now, use bearer tokens or stdio versions with built-in OAuth.
CI/CD Examples
GitHub Actions
name: Add MCP
on: push
jobs:
add-mcp:
runs-on: ubuntu-latest
steps:
- name: Install NCP
run: npm install -g @portel/ncp
- name: Add GitHub MCP
run: ncp add github --env GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
- name: Add Notion MCP
run: ncp add notion --token ${{ secrets.NOTION_TOKEN }}Shell Script
#!/bin/bash
# setup-mcps.sh
# Load secrets from environment
set -a
source .env
set +a
# Add MCPs non-interactively
ncp add github --env GITHUB_TOKEN="$GITHUB_TOKEN"
ncp add slack --env SLACK_BOT_TOKEN="$SLACK_BOT_TOKEN"
ncp add notion --token "$NOTION_TOKEN"
echo "✅ All MCPs configured"Need Help?
- Documentation: https://github.com/portel-dev/ncp/tree/main/docs
- Issues: https://github.com/portel-dev/ncp/issues
- Discord: https://discord.gg/portel