Skip to content
Browse documentation
DocsMCP

MCP server

Connect any Model Context Protocol AI agent (ChatGPT, Claude, Cursor, VS Code, custom clients) to your panel account so it can manage your servers, files, backups, databases, tickets and billing for you.

StormNodes developer reference

Overview

Connect an AI assistant to your StormPanel account to manage your game servers through Model Context Protocol (MCP). You can ask it to list servers, start or stop them, send console commands, edit files, manage backups, and use the other tools listed below.

Your AI uses your account permissions. It cannot access servers or perform actions that your account cannot access. Tool calls are recorded in your account activity log.

ChatGPT connects through a sign-in and authorization page. Clients that support custom headers can connect with a dedicated panel API key. Both methods give the AI the same access as your account.

Server URL

Use the following URL when adding StormPanel to your AI client. Select Streamable HTTP if the client asks for a transport type.

Opening this URL directly in a browser displays a method-not-allowed message. Add it in your AI client instead.

Server URL: https://stormnodes.xyz/api/mcp
Transport:  Streamable HTTP

Connecting with an API key

For clients that support an Authorization header, create a dedicated key under Account → API keys. Give it a recognizable name, such as "claude-desktop", so you can disconnect that client without affecting your other integrations.

Copy the full token shown when you create the key. It contains a public and private part joined with a dot. Store it in your client's credential settings and treat it like a password. Do not share it or include it in public repositories.

Add the token as a Bearer credential using the header below. Your panel login cookie cannot be used as an MCP credential. ChatGPT users should follow the ChatGPT setup section instead.

Authorization: Bearer <public_key>.<private_key>

Good to know

To disconnect a client or replace a leaked key, delete or regenerate its key under Account → API keys.

Setup: Claude Desktop

Claude Desktop connects to remote HTTP MCP servers natively. Open Settings → Connectors (or Developer settings, depending on version), choose to add a remote MCP server, and point it at the panel endpoint with your bearer token. Claude will perform the MCP handshake and list your tools automatically.

On versions without native remote support, install the mcp-remote adapter (npx mcp-remote) in the desktop configuration file (claude_desktop_config.json) and restart the app.

// Native remote connector
Server URL:   https://stormnodes.xyz/api/mcp
Custom header: Authorization: Bearer fp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.fp_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

// Via mcp-remote (claude_desktop_config.json)
{
  "mcpServers": {
    "stormpanel": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://stormnodes.xyz/api/mcp",
               "--header", "Authorization: Bearer fp_PUBLIC.fp_PRIVATE"]
    }
  }
}

Setup: Claude Code

Claude Code manages remote MCP servers through its CLI. The command below registers the panel as an HTTP MCP server for your user scope; adjust --scope project to store it in a project instead. After adding it, run /mcp inside a session to verify the server connects and shows its tools.

claude mcp add --transport http --scope user stormpanel \
  https://stormnodes.xyz/api/mcp \
  --header "Authorization: Bearer fp_PUBLIC.fp_PRIVATE"

# verify
claude mcp list

Setup: Cursor

Cursor reads MCP servers from ~/.cursor/mcp.json (or .cursor/mcp.json inside a project). Add the panel as an HTTP server with your Authorization header, then enable the "stormpanel" server in Cursor settings → MCP. The tool list appears after the first successful handshake.

{
  "mcpServers": {
    "stormpanel": {
      "url": "https://stormnodes.xyz/api/mcp",
      "headers": {
        "Authorization": "Bearer fp_PUBLIC.fp_PRIVATE"
      }
    }
  }
}

Setup: VS Code and other clients

VS Code (Copilot Chat agent mode) configures MCP servers in .vscode/mcp.json or user settings; other MCP-capable clients (Windsurf, Cline, Zed, custom SDK clients) accept the same shape. Any client that supports the Streamable HTTP transport with custom headers works: point it at the endpoint, attach the Authorization header, and the handshake negotiates the protocol version automatically.

{
  "servers": {
    "stormpanel": {
      "type": "http",
      "url": "https://stormnodes.xyz/api/mcp",
      "headers": {
        "Authorization": "Bearer fp_PUBLIC.fp_PRIVATE"
      }
    }
  }
}

Setup: ChatGPT

Open ChatGPT Settings → Apps or Connectors and choose to create a custom MCP server. Enter a name, such as "StormPanel", and use https://stormnodes.xyz/api/mcp as the Server URL.

Select OAuth or no authentication. In Advanced OAuth settings, use Dynamic Client Registration (DCR) and the mcp scope. You do not need to enter a client ID, client secret, or tunnel ID. The notice that CIMD is unavailable is expected when using DCR.

Create the connection. In the authorization page, sign in with your StormPanel account, review the requested access, and click Authorize. Complete two-factor authentication if your account requires it.

Return to ChatGPT, enable the connection for your conversation, and try a read-only request such as "list my game servers". Review changes the AI proposes before letting it modify your server.

To disconnect ChatGPT, delete its MCP OAuth key under Account → API keys. If the connection expires or is revoked, reconnect from ChatGPT and authorize it again.

Name:                StormPanel
Server URL:          https://stormnodes.xyz/api/mcp
Authentication:      OAuth or no authentication
Client registration: Dynamic Client Registration (DCR)
Scope:               mcp

Good to know

If discovery or registration fails, check the Server URL and contact StormNodes support with the error message. If authorization stalls, close the authorization page and start the connection again from ChatGPT. Check that your browser allows the login popup. If tools are missing, enable the connection in the conversation's tools menu.

Protocol and raw request examples

The endpoint speaks JSON-RPC 2.0. A minimal conversation is three calls: initialize (handshake), tools/list (discover tools), and tools/call (execute one). Notifications such as notifications/initialized are accepted with HTTP 202 and no body. Batching (JSON arrays) is not supported and returns a 400 error.

These curl examples are handy for smoke-testing a token or wiring custom clients. Note that tools/call arguments are always a JSON object, and errors inside a tool come back as a result with "isError": true rather than as an HTTP error.

# 1) Handshake
curl -s https://stormnodes.xyz/api/mcp \
  -H "Authorization: Bearer fp_PUBLIC.fp_PRIVATE" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
       "params":{"protocolVersion":"2025-06-18",
                 "clientInfo":{"name":"curl","version":"1.0"}}}'

# 2) Discover tools
curl -s https://stormnodes.xyz/api/mcp \
  -H "Authorization: Bearer fp_PUBLIC.fp_PRIVATE" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# 3) Call a tool
curl -s https://stormnodes.xyz/api/mcp \
  -H "Authorization: Bearer fp_PUBLIC.fp_PRIVATE" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
       "params":{"name":"list_servers","arguments":{"limit":20}}}'

# 4) Ping
curl -s https://stormnodes.xyz/api/mcp \
  -H "Authorization: Bearer fp_PUBLIC.fp_PRIVATE" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":4,"method":"ping"}'

Tool catalog

The 137 tools below are exposed to your AI. Every server-scoped tool takes the server short UUID (uuidShort) that list_servers returns, plus the arguments shown. Tools marked DESTRUCTIVE in their description permanently change or delete data. The AI is instructed to confirm with you before calling them.

Calling a tool your account lacks permission for (for example a subuser without file delete rights) returns the same permission error the panel UI would show. That is the permission model working: the AI is bound to your account rights, never above them.

ACCOUNT & PLATFORM
  get_account                        account profile, 2FA state, preferences
  list_user_activities (page,limit)  recent account activity
  list_notifications (page,limit)    account notifications
  dismiss_notification (id)          mark a notification read
  get_node_status                    infrastructure node health
  list_kb_categories / search_kb_articles / get_kb_article

SERVERS
  list_servers (page,limit,search)   your servers + short UUIDs (start here)
  get_server (uuidShort)             full details, SFTP, variables, limits
  update_server (name,description,image,spell_id,variables,startup,wipe_files)
  reinstall_server (uuidShort,wipe_files)            DESTRUCTIVE
  delete_server (uuidShort)                          DESTRUCTIVE
  get_server_jwt (uuidShort)         short-lived console websocket token
  list_server_splits / create_server_split

POWER & CONSOLE
  power_action (uuidShort,action)    action: start | stop | restart | kill
  send_console_command (uuidShort,command)
  get_server_logs (uuidShort)        read console output after commands
  get_install_logs (uuidShort)

FILES
  list_files (uuidShort,path)        directory listing with sizes
  read_file (uuidShort,path)         file contents (text)
  write_file (uuidShort,path,content)            create/overwrite text file
  upload_file (uuidShort,filename,content_base64,path)
  rename_files (uuidShort,root,files[{from,to}])
  copy_files (uuidShort,location,files[])
  delete_files (uuidShort,root,files[])          DESTRUCTIVE
  create_directory (uuidShort,path,name)
  compress_files (uuidShort,root,files[],name,extension)
  decompress_archive (uuidShort,root,file)
  change_file_permissions (uuidShort,root,files[{name,mode}])
  pull_file (uuidShort,url,root,fileName,foreground)  download URL onto server
  download_file (uuidShort,path)     signed download URL
  get_folder_size (uuidShort,path)
  list_pull_processes (uuidShort)    background transfers
  wipe_all_files (uuidShort)                      DESTRUCTIVE

BACKUPS
  list_backups / create_backup (name) / get_backup (backupUuid)
  delete_backup (backupUuid)                       DESTRUCTIVE
  restore_backup (backupUuid)                      DESTRUCTIVE
  get_backup_download_url (backupUuid)
  lock_backup / unlock_backup (backupUuid)
  get_restore_status (uuidShort)

DATABASES
  list_databases / create_database (database,remote)
  get_database / update_database / delete_database (databaseId)
  list_database_hosts
  export_database_dump (databaseId)
  import_database_dump (databaseId,content)       raw SQL
  list_database_backups / create_database_backup (databaseId)
  restore_database_backup / delete_database_backup (backupUuid)

SCHEDULES & TASKS
  list_schedules / create_schedule (name,minute,hour,day_of_week,day_of_month,is_active)
  get_schedule / update_schedule / delete_schedule / toggle_schedule (scheduleId)
  list_schedule_tasks (scheduleId)
  create_schedule_task (scheduleId,action,payload,time_offset,sequence)
  update_schedule_task / delete_schedule_task (scheduleId,taskId)

SUBUSERS & PORTS
  list_subusers / create_subuser (email,permissions[])
  get_subuser / update_subuser / delete_subuser (subuserId)
  list_subuser_permissions           valid permission keys
  list_allocations / list_available_allocations / auto_allocate
  set_primary_allocation / delete_allocation (allocationId)

STARTUP
  list_startup_command_reviews / submit_startup_command_review (command,reason)

PLAYERS (Minecraft)
  list_players (page,limit,search) / list_online_players
  get_player_details / get_player_chat_history (identifier)
  run_player_action (identifier,action,reason,value)  kick/ban/op/gamemode...
  get_player_list (listType)         whitelist | banlist | operators
  add_player_list_entry / remove_player_list_entry (listType,identifier)

PLUGINS, PACKAGES, VERSIONS, TEMPLATES, WORLDS
  search_plugins (search,page,limit) / list_plugin_versions (resourceId)
  install_plugin (resourceId,version) / uninstall_plugin (resourceId)
  get_plugin_install_status
  search_packages (runtime,search) / list_installed_packages (runtime)
  install_package / uninstall_package (runtime,package,version)
  list_software / list_software_versions (type)
  install_software_version (type,version)
  list_templates (page,limit) / install_template (templateId)   DESTRUCTIVE
  rollback_template
  list_worlds / get_world_info / get_world_properties (worldName)
  update_world_properties (worldName,properties)
  delete_world (worldName)                          DESTRUCTIVE

NETWORK
  list_subdomains / create_subdomain (subdomain,domain) / delete_subdomain (uuid)
  list_firewall_rules / create_firewall_rule (port,protocol,source,note)
  update_firewall_rule / delete_firewall_rule (ruleId)

TICKETS
  list_tickets (page,limit,status) / list_ticket_categories
  create_ticket (subject,message,category,priority,server)
  get_ticket (uuid) / reply_to_ticket (uuid,message)

BILLING (read + subscription lifecycle)
  get_billing_summary / get_billing_workspace
  list_receipts / list_invoices / get_invoice (invoiceId)
  renew_subscription (subscriptionId)
  set_subscription_auto_renew (subscriptionId,enabled)
  cancel_subscription (subscriptionId)
  get_wallet_status / get_referral_summary

ALERTS, SSH KEYS, LOGS
  list_alert_incidents / acknowledge_alert_incident / resolve_alert_incident (incidentId)
  list_ssh_keys / create_ssh_key (name,public_key) / delete_ssh_key (id)
  get_server_activities (uuidShort,page,limit)

Permissions and account access

Connecting an AI gives it access to the actions available to your account. Server ownership, subuser permissions, suspensions, and server locks still apply.

Review your account activity log to see which tools the AI has called. Disconnect clients you no longer use by deleting their keys under Account → API keys.

MCP does not expose panel administration, API key creation, or payment checkout. Some tools can delete files, change settings, cancel subscriptions, or spend an existing wallet balance. Read the tool descriptions and review consequential actions before approving them.

Good to know

Use a separate key for each client. Keep credentials private and remove access when you stop using a client.

Rate limits and file sizes

The MCP endpoint allows up to 120 requests per minute per client IP by default. Individual tools also follow the panel's limits for the action being performed. If you receive a rate-limit error, wait before trying again and reduce how many actions your AI sends at once.

Request bodies are limited to 8 MiB and tool output to 512 KiB by default. Large results may be shortened. Binary files are returned as download links rather than displayed as text.

Default request limit: 120 requests/minute/IP
Default request size:  8 MiB
Default output size:   512 KiB

Errors and troubleshooting

MCP protocol problems come back as JSON-RPC error objects; tool-level problems come back as tool results with "isError": true whose text contains the panel error code (SERVER_NOT_FOUND, ACCESS_DENIED, RATE_LIMITED, and so on). Use the table to diagnose what you are seeing.

HTTP 401  Invalid API key, a session cookie was sent instead of a Bearer key,
           or an OAuth connection (ChatGPT) was revoked/expired. Reconnect it.
HTTP 403  Opaque origin (Origin: null) refused, or the account is banned.
HTTP 400  Malformed JSON-RPC (parse error, batching, wrong version, bad id),
           or an unsupported pinned MCP-Protocol-Version header.
HTTP 405  GET/DELETE on /api/mcp. Use POST.
HTTP 413  Request body over 8 MiB.
HTTP 429  Rate limited, slow down; per-route limits apply per account.

JSON-RPC -32700  Body is not valid JSON.
JSON-RPC -32600  Invalid request envelope (batching, wrong jsonrpc, params not an object).
JSON-RPC -32601  Unknown method (only initialize, ping, tools/list, tools/call).
JSON-RPC -32602  Bad tool arguments: unknown tool name, missing required argument,
                  invalid uuidShort/action/world name, invalid base64, oversized content.
JSON-RPC -32603  Unexpected server error (logged server-side with request context).

Tool result isError:true  The panel API rejected the operation. Read error_code in
                           the returned JSON (permissions, server state, validation).

OAuth endpoints (token/revoke) speak RFC 6749 §5.2 errors instead:
  invalid_client / invalid_grant / invalid_request / invalid_scope /
  unsupported_grant_type / temporarily_unavailable.

Good to know

Claude/Cursor showing no tools? Verify the key works with the curl ping example, then check that your client sends the Authorization header on every request (some clients require it explicitly in the server entry rather than an OAuth flow).