An MCP server for managing Netskope Network Private Access (NPA) infrastructure through Large Language Models (LLMs).
A Model Context Protocol (MCP) server for managing Netskope Network Private Access (NPA) infrastructure through Large Language Models (LLMs).
Still lots of work needs to be done for all 50 tools to be operational, i strongly advise against using this with any production environment
https://github.com/johnneerdael/netskope-mcp/raw/refs/heads/main/demo.mov
Install the package using npm:
npm install @johnneerdael/netskope-mcp
Clone the repository and install dependencies:
git clone https://github.com/johnneerdael/netskope-mcp.git
cd netskope-mcp
npm install
npm run build
Add the following configuration to your MCP settings file:
For NPM installation:
{
"mcpServers": {
"netskope-mcp": {
"command": "wsl.exe",
"args": [
"bash",
"-c",
"source ~/.nvm/nvm.sh && NETSKOPE_BASE_URL=https://your-tenant.goskope.com NETSKOPE_API_KEY=your-token npx -y @johnneerdael/netskope-mcp"
]
}
}
}
For local development:
{
"mcpServers": {
"netskope-mcp": {
"command": "wsl.exe",
"args": [
"bash",
"-c",
"cd /path/to/netskope-mcp && NETSKOPE_BASE_URL=https://your-tenant.goskope.com NETSKOPE_API_KEY=your-token node dist/cli.js"
]
}
}
}
For NPM installation:
{
"mcpServers": {
"netskope-mcp": {
"command": "npx",
"args": ["-y", "@johnneerdael/netskope-mcp"],
"env": {
"NETSKOPE_BASE_URL": "https://your-tenant.goskope.com",
"NETSKOPE_API_KEY": "your-token"
}
}
}
}
For local development:
{
"mcpServers": {
"netskope-mcp": {
"command": "node",
"args": ["dist/cli.js"],
"cwd": "/path/to/netskope-mcp",
"env": {
"NETSKOPE_BASE_URL": "https://your-tenant.goskope.com",
"NETSKOPE_API_KEY": "your-token"
}
}
}
}
The Netskope NPA MCP Server requires the following environment variables to be configured for proper operation:
NETSKOPE_BASE_URL
https://your-tenant.goskope.com
NETSKOPE_API_KEY
030f31f7d57fd94834af57a3edc4bbda
export NETSKOPE_BASE_URL="https://dev-tenant.goskope.com"
export NETSKOPE_API_KEY="your-development-token"
export NETSKOPE_BASE_URL="https://prod-tenant.goskope.com"
export NETSKOPE_API_KEY="your-production-token"
getAlertConfig
{
adminUsers: string[], // Array of admin user emails to notify
eventTypes: string[], // Array of event types to monitor
selectedUsers: string // Additional users to notify
}
UPGRADE_WILL_START
: Notification before a publisher upgrade beginsUPGRADE_STARTED
: Notification when upgrade process initiatesUPGRADE_SUCCEEDED
: Notification upon successful upgrade completionUPGRADE_FAILED
: Notification if upgrade process failsCONNECTION_FAILED
: Notification when publisher connection issues occurgetAlertConfig
to return the current list of admin users and their notification preferences."getAlertConfig
to ensure the right team members will be notified of upgrade events."getAlertConfig
to show which critical events are being tracked and who receives notifications."updateAlertConfig
{
adminUsers: string[], // Array of admin user emails to receive notifications
eventTypes: string[], // Array of event types to monitor
selectedUsers: string // Additional users to receive notifications
}
listLocalBrokers
fields
: Array of specific fields to return in the response{
status: 'success' | 'not found',
total: number,
data: Array<{
id: number, // Unique identifier for the local broker
name: string, // Display name of the local broker
common_name: string, // Common name used for broker identification
registered: boolean // Registration status of the broker
}>
}
createLocalBroker
{
name: string // Name for the new local broker
}
{
status: 'success' | 'not found',
data: {
id: number, // Assigned unique identifier
name: string, // Configured broker name
common_name: string, // Assigned common name
registered: boolean // Initial registration status
}
}
getLocalBroker
id
: Numeric identifier of the local broker to retrieve{
status: 'success' | 'not found',
data: {
id: number, // Broker's unique identifier
name: string, // Broker's display name
common_name: string, // Broker's common name
registered: boolean // Current registration status
}
}
updateLocalBroker
{
id: number, // Identifier of broker to update
name: string // New name for the broker
}
{
status: 'success' | 'not found',
data: {
id: number, // Broker's identifier
name: string, // Updated broker name
common_name: string, // Broker's common name
registered: boolean // Current registration status
}
}
deleteLocalBroker
id
: Numeric identifier of the local broker to delete{
status: 'success' | 'not found'
}
getBrokerConfig
{
status: 'success' | 'not found',
data: {
hostname: string // Global hostname configuration
}
}
updateBrokerConfig
{
hostname: string // New hostname configuration
}
{
status: 'success' | 'not found',
data: {
hostname: string // Updated hostname configuration
}
}
generateLocalBrokerRegistrationToken
id
: Numeric identifier of the local broker{
status: 'success' | 'not found',
data: {
token: string // Generated registration token
}
}
listRules
fields
: Array of specific fields to returnfilter
: Filter criteria for the ruleslimit
: Maximum number of rules to returnoffset
: Number of rules to skipsortby
: Field to sort bysortorder
: Sort direction ('asc' or 'desc'){
data: {
rules: Array<{
id: number,
name: string,
description?: string,
enabled: boolean,
action: 'allow' | 'block',
policy_group_id: number,
priority: number,
conditions: Array<{
type: 'private_app' | 'user' | 'group' | 'organization_unit' | 'location' | 'device',
operator: 'in' | 'not_in' | 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with',
value: string | string[] | number | number[]
}>,
created_at: string,
updated_at: string
}>
},
status: 'success' | 'error',
total: number
}
getRule
id
: Numeric identifier of the policy rulefields
: Array of specific fields to return{
data: {
id: number,
name: string,
description?: string,
enabled: boolean,
action: 'allow' | 'block',
policy_group_id: number,
priority: number,
conditions: Array<{
type: 'private_app' | 'user' | 'group' | 'organization_unit' | 'location' | 'device',
operator: 'in' | 'not_in' | 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with',
value: string | string[] | number | number[]
}>,
created_at: string,
updated_at: string
},
status: 'success' | 'error'
}
createRule
{
name: string, // Rule name
description?: string, // Optional rule description
enabled: boolean, // Rule status
action: 'allow' | 'block', // Access action
policy_group_id: number, // Associated policy group
priority: number, // Rule priority
conditions: Array<{
type: 'private_app' | 'user' | 'group' | 'organization_unit' | 'location' | 'device',
operator: 'in' | 'not_in' | 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with',
value: string | string[] | number | number[]
}>
}
updateRule
id
: Numeric identifier of the rule to updatedata
: Updated rule configuration following the same schema as create_rule{
data: {
// Updated rule details (same as get_rule response)
},
status: 'success' | 'error'
}
deleteRule
id
: Numeric identifier of the rule to delete{
status: 'success' | 'error'
}
createPrivateApp
{
app_name: string, // Name of the private application
host: string, // Host address of the application
clientless_access: boolean, // Enable clientless access
is_user_portal_app: boolean, // Show in user portal
protocols: Array<{
port: string, // Port number
type: 'tcp' | 'udp' // Protocol type
}>,
publisher_tags?: Array<{ // Optional publisher tags
tag_name: string
}>,
publishers: Array<{ // Associated publishers
publisher_id: string,
publisher_name: string
}>,
trust_self_signed_certs: boolean, // Trust self-signed certificates
use_publisher_dns: boolean, // Use publisher DNS
allow_unauthenticated_cors?: boolean, // Optional CORS settings
allow_uri_bypass?: boolean, // Optional URI bypass
bypass_uris?: string[], // Optional bypass URIs
real_host?: string, // Optional real host
app_option?: Record<string, unknown> // Additional options
}
{
data: {
allow_unauthenticated_cors: boolean,
allow_uri_bypass: boolean,
uribypass_header_value: string,
bypass_uris: string[],
app_option: Record<string, unknown>,
clientless_access: boolean,
host: string,
id: number,
is_user_portal_app: boolean,
name: string,
protocols: Array<{
ports: string[],
type: string
}>,
real_host: string,
service_publisher_assignments: Array<{
primary: boolean,
publisher_id: number,
publisher_name: string,
reachability: {
error_code: number,
error_string: string,
reachable: boolean
},
service_id: number
}>,
tags: Array<{
tag_id: number,
tag_name: string
}>,
trust_self_signed_certs: boolean,
use_publisher_dns: boolean
},
status: 'success' | 'not found'
}
updatePrivateApp
{
id: number, // Application ID
// All other fields same as create_private_app
}
deletePrivateApp
id
: Numeric identifier of the private application{
status: number,
result: string
}
getPrivateApp
id
: Numeric identifier of the private applicationlistPrivateApps
fields
: Specific fields to returnfilter
: Filter criteriaquery
: Search querylimit
: Maximum number of resultsoffset
: Number of results to skip{
data: Array<{
// Same fields as get_private_app response
}>,
status: 'success' | 'not found',
total: number
}
getPrivateAppTags
query
: Search query for tagslimit
: Maximum number of tagsoffset
: Number of tags to skip{
data: Array<{
tag_id: number,
tag_name: string
}>,
status: 'success' | 'not found'
}
createPrivateAppTags
id
: Application identifiertags
: Array of tag objectsupdatePrivateAppTags
ids
: Array of application identifierstags
: Array of updated tag objectsupdatePrivateAppPublishers
{
private_app_ids: string[], // Application IDs
publisher_ids: string[] // Publisher IDs
}
deletePrivateAppPublishers
{
private_app_ids: string[], // Application IDs
publisher_ids: string[] // Publisher IDs to remove
}
getDiscoverySettings
getPolicyInUse
ids
: Array of application identifierslistPublishers
fields
: Specific fields to return in the response{
data: {
publishers: Array<{
apps_count: number,
assessment: {
ca_certs_status: {
hashes: string[],
last_modified: number
},
eee_support: boolean,
hdd_free: string,
hdd_total: string,
ip_address: string,
latency: number,
version: string
},
capabilities: {
DTLS: boolean,
EEE: boolean,
auto_upgrade: boolean,
nwa_ba: boolean,
pull_nsconfig: {
orgkey_exist: boolean,
orguri_exist: boolean
}
},
common_name: string,
connected_apps: string[],
id: number,
lbrokerconnect: boolean,
name: string,
publisher_upgrade_profiles_id: number,
registered: boolean,
status: 'connected' | 'not registered',
stitcher_id: number,
sticher_pop: string,
upgrade_request: boolean,
upgrade_status: {
upstat: string
}
}>
},
status: 'success' | 'not found',
total: number
}
getPublisher
id
: Numeric identifier of the publishercreatePublisher
{
name: string, // Publisher name
lbrokerconnect?: boolean, // Optional local broker connection
publisher_upgrade_profiles_id?: number // Optional upgrade profile assignment
}
patchPublisher
{
name: string, // Publisher name
id?: number, // Optional publisher ID
lbrokerconnect?: boolean, // Optional local broker connection
publisher_upgrade_profiles_id?: number // Optional upgrade profile assignment
}
updatePublisher
{
id: number, // Publisher ID
name: string, // Publisher name
lbrokerconnect?: boolean, // Optional local broker connection
tags?: Array<{ // Optional tags
tag_id: number,
tag_name: string
}>
}
deletePublisher
id
: Numeric identifier of the publisher to delete{
status: 'success' | 'error'
}
bulkUpgradePublishers
{
publishers: {
apply: {
upgrade_request: boolean // Whether to request upgrade
},
id: string[] // Array of publisher IDs
}
}
{
data: {
publishers: Array<PublisherResponse>
},
status: 'success' | 'not found'
}
getReleases
{
data: Array<{
docker_tag: string,
is_recommended: boolean,
release_type: 'Beta' | 'Latest' | 'Latest-1' | 'Latest-2',
version: string
}>,
status: 'success' | 'not found'
}
getPrivateApps
publisherId
: Numeric identifier of the publishergeneratePublisherRegistrationToken
publisherId
: Numeric identifier of the publisher{
data: {
token: string // Registration token
},
status: string
}
listUpgradeProfiles
{
data: {
upgrade_profiles: Array<{
id: number,
external_id: number,
name: string,
docker_tag: string,
enabled: boolean,
frequency: string, // Cron format: minute hour day * DAY_OF_WEEK
timezone: string, // Standard timezone identifier
release_type: 'Beta' | 'Latest' | 'Latest-1' | 'Latest-2',
created_at: string,
updated_at: string,
next_update_time?: number,
num_associated_publisher: number,
upgrading_stage?: number,
will_start?: boolean
}>
},
status: 'success' | 'not found',
total: number
}
getUpgradeProfile
id
: Numeric identifier of the upgrade profilecreateUpgradeProfile
{
name: string, // Profile name
enabled: boolean, // Profile status
docker_tag: string, // Docker image tag for upgrade
frequency: string, // Cron schedule format
timezone: string, // Timezone for schedule
release_type: 'Beta' | 'Latest' | 'Latest-1' | 'Latest-2'
}
updateUpgradeProfile
id
: Profile identifierdata
: Updated profile configuration (same schema as create_upgrade_profile){
data: {
// Updated profile details (same as get_upgrade_profile response)
},
status: 'success' | 'not found'
}
deleteUpgradeProfile
id
: Numeric identifier of the profile to delete{
status: 'success' | 'not found'
}
updatePublisherAssociation
{
private_app_ids: string[], // Array of private application IDs
publisher_ids: string[] // Array of publisher IDs
}
{
status: 'success' | 'error',
data: {
private_app_ids: string[],
publisher_ids: string[]
}
}
deletePublisherAssociation
{
private_app_ids: string[], // Array of private application IDs
publisher_ids: string[] // Array of publisher IDs to remove
}
getUserDiagnostics
{
status: 'success' | 'error',
data: {
user_id: string,
diagnostics: Array<{
private_app_id: string,
private_app_name: string,
publisher_id: string,
publisher_name: string,
status: string,
timestamp: string
}>
}
}
getDeviceDiagnostics
deviceId
: Device identifierprivateAppId
: Private application identifier{
status: 'success' | 'error',
data: {
device_id: string,
private_app_id: string,
diagnostics: Array<{
publisher_id: string,
publisher_name: string,
status: string,
timestamp: string
}>
}
}
validateName
{
resourceType: 'publisher' | 'private_app' | 'policy' | 'policy_group' | 'upgrade_profile',
name: string,
tagType?: 'publisher' | 'private_app'
}
{
status: 'success' | 'error',
data: {
valid: boolean,
message?: string
}
}
validateResource
{
resourceType: 'publisher' | 'private_app' | 'policy' | 'policy_group' | 'upgrade_profile',
data: {
name: string,
// Additional resource-specific fields
}
}
{
status: 'success' | 'error',
data: {
valid: boolean,
errors?: string[]
}
}
searchResources
{
resourceType: 'publishers' | 'private_apps',
query: string
}