Skip to main content
Glama

manage_pubnub_account

Manage PubNub account applications and API keys by creating, listing, or deleting test items. Uses environment variables for authentication, ensuring secure and controlled account modifications.

Instructions

Manages the users PubNub account apps and API key settings. Uses PUBNUB_EMAIL and PUBNUB_PASSWORD environment variables for authentication. Supports creating, listing, and deleting apps and API keys. Delete action only works on test apps/keys (with "Test App" or "Test Key" in the name) for safety.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesThe action to perform: "create" to create new, "list" to list existing, "delete" to delete test items
subjectYesThe subject to manage: "app" for applications, "api_key" for API keys

Implementation Reference

  • The primary handler function for the 'manage_pubnub_account' MCP tool. Implements create, list, and delete operations for PubNub applications ('app') and API keys ('api_key') using authenticated requests to the PubNub Admin API (https://admin.pubnub.com/api). Handles authentication via PUBNUB_EMAIL/PUBNUB_PASSWORD env vars, with session retry logic.
    toolHandlers['manage_pubnub_account'] = async ({ subject, action }) => { try { // Handle list actions if (action === 'list') { if (subject === 'app') { // List apps without keys const response = await makeAuthenticatedRequest( `https://admin.pubnub.com/api/apps?owner_id=${accountId}&no_keys=1` ); if (!response.ok) { throw new Error(`Failed to list apps: ${response.status} ${response.statusText}`); } const data = await response.json(); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], }; } else if (subject === 'api_key') { // List all apps with their keys const response = await makeAuthenticatedRequest( `https://admin.pubnub.com/api/apps?owner_id=${accountId}` ); if (!response.ok) { throw new Error(`Failed to list API keys: ${response.status} ${response.statusText}`); } const data = await response.json(); // Extract just the keys from all apps for a cleaner response const allKeys = []; if (data.result && Array.isArray(data.result)) { data.result.forEach(app => { if (app.keys && Array.isArray(app.keys)) { app.keys.forEach(key => { allKeys.push({ app_name: app.name, app_id: app.id, key_id: key.id, key_name: key.properties?.name || 'Unnamed Key', publish_key: key.publish_key, subscribe_key: key.subscribe_key, secret_key: key.secret_key, status: key.status, type: key.type }); }); } }); } return { content: [{ type: 'text', text: JSON.stringify({ total_keys: allKeys.length, keys: allKeys }, null, 2) }], }; } } // Handle create actions if (action === 'create') { if (subject === 'app') { // Create a new app const appName = `New App ${new Date().toISOString()}`; const response = await makeAuthenticatedRequest( 'https://admin.pubnub.com/api/apps', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ owner_id: accountId, name: appName }), } ); if (!response.ok) { throw new Error(`Failed to create app: ${response.status} ${response.statusText}`); } const data = await response.json(); return { content: [{ type: 'text', text: `App created successfully!\n${JSON.stringify(data, null, 2)}` }], }; } else if (subject === 'api_key') { // First, we need to get the list of apps to pick one const appsResponse = await makeAuthenticatedRequest( `https://admin.pubnub.com/api/apps?owner_id=${accountId}&no_keys=1` ); if (!appsResponse.ok) { throw new Error(`Failed to get apps: ${appsResponse.status} ${appsResponse.statusText}`); } const appsData = await appsResponse.json(); if (!appsData.result || appsData.result.length === 0) { throw new Error('No apps found. Please create an app first.'); } // Use the first app for now const appId = appsData.result[0].id; const keyName = `New Key ${new Date().toISOString()}`; // Create a new API key const response = await makeAuthenticatedRequest( 'https://admin.pubnub.com/api/keys', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ app_id: appId, type: 1, // production properties: { name: keyName, history: 1, message_storage_ttl: 30, presence: 1, wildcardsubscribe: 1 } }), } ); if (!response.ok) { const errorText = await response.text(); throw new Error(`Failed to create API key: ${response.status} ${response.statusText} - ${errorText}`); } const data = await response.json(); return { content: [{ type: 'text', text: `API key created successfully in app "${appsData.result[0].name}"!\n${JSON.stringify(data, null, 2)}` }], }; } } // Handle delete actions if (action === 'delete') { if (subject === 'app') { // Get list of apps to find the most recently created test app const appsResponse = await makeAuthenticatedRequest( `https://admin.pubnub.com/api/apps?owner_id=${accountId}&no_keys=1` ); if (!appsResponse.ok) { throw new Error(`Failed to get apps: ${appsResponse.status} ${appsResponse.statusText}`); } const appsData = await appsResponse.json(); if (!appsData.result || appsData.result.length === 0) { throw new Error('No apps found to delete.'); } // Find a test app to delete (look for apps with "Test App" in the name) const testApps = appsData.result.filter(app => app.name.includes('Test App')); if (testApps.length === 0) { return { content: [{ type: 'text', text: `No test apps found to delete. Only apps with "Test App" in the name can be deleted via this tool for safety.` }], isError: true, }; } // Sort by created date (descending) and delete the most recent test app const appToDelete = testApps.sort((a, b) => b.created - a.created)[0]; // Delete the app const deleteResponse = await makeAuthenticatedRequest( `https://admin.pubnub.com/api/apps/${appToDelete.id}`, { method: 'DELETE', } ); if (!deleteResponse.ok) { const errorText = await deleteResponse.text(); throw new Error(`Failed to delete app: ${deleteResponse.status} ${deleteResponse.statusText} - ${errorText}`); } return { content: [{ type: 'text', text: `App deleted successfully!\nDeleted app: "${appToDelete.name}" (ID: ${appToDelete.id})` }], }; } else if (subject === 'api_key') { // Get all apps with their keys const appsResponse = await makeAuthenticatedRequest( `https://admin.pubnub.com/api/apps?owner_id=${accountId}` ); if (!appsResponse.ok) { throw new Error(`Failed to get API keys: ${appsResponse.status} ${appsResponse.statusText}`); } const appsData = await appsResponse.json(); // Find test keys to delete (look for keys with "Test Key" in the name) let keyToDelete = null; let appContainingKey = null; if (appsData.result && Array.isArray(appsData.result)) { for (const app of appsData.result) { if (app.keys && Array.isArray(app.keys)) { const testKeys = app.keys.filter(key => key.properties?.name && key.properties.name.includes('Test Key') ); if (testKeys.length > 0) { // Sort by ID (descending) to get the most recent test key keyToDelete = testKeys.sort((a, b) => b.id - a.id)[0]; appContainingKey = app; break; } } } } if (!keyToDelete) { return { content: [{ type: 'text', text: `No test API keys found to delete. Only keys with "Test Key" in the name can be deleted via this tool for safety.` }], isError: true, }; } // Delete the API key const deleteResponse = await makeAuthenticatedRequest( `https://admin.pubnub.com/api/keys/${keyToDelete.id}`, { method: 'DELETE', } ); if (!deleteResponse.ok) { const errorText = await deleteResponse.text(); throw new Error(`Failed to delete API key: ${deleteResponse.status} ${deleteResponse.statusText} - ${errorText}`); } return { content: [{ type: 'text', text: `API key deleted successfully!\nDeleted key: "${keyToDelete.properties.name}" (ID: ${keyToDelete.id}) from app "${appContainingKey.name}"` }], }; } } return { content: [{ type: 'text', text: `Unsupported combination: ${action} ${subject}` }], isError: true, }; } catch (err) { return { content: [{ type: 'text', text: `Error managing PubNub account: ${err.message}` }], isError: true, }; } };
  • Input schema definition for the tool using Zod validation. Defines parameters 'subject' (enum: ['app', 'api_key']) and 'action' (enum: ['create', 'list', 'delete']). Includes detailed description.
    toolDefinitions['manage_pubnub_account'] = { name: 'manage_pubnub_account', description: 'Manages the users PubNub account apps and API key settings. Uses PUBNUB_EMAIL and PUBNUB_PASSWORD environment variables for authentication. Supports creating, listing, and deleting apps and API keys. Delete action only works on test apps/keys (with "Test App" or "Test Key" in the name) for safety.', parameters: { subject: z.enum(managementSubjects).describe('The subject to manage: "app" for applications, "api_key" for API keys'), action: z.enum(managementActions).describe('The action to perform: "create" to create new, "list" to list existing, "delete" to delete test items'), } };
  • index.js:1363-1394 (registration)
    Dynamic registration function for all MCP tools on the McpServer instance. Specifically excludes 'manage_pubnub_account' in --chat-sdk mode via chatSdkExcludedTools array. Called at line 1397 for main server.
    function registerAllTools(serverInstance, chatSdkMode = false) { // Tools to exclude when in chat SDK mode const chatSdkExcludedTools = [ 'read_pubnub_sdk_docs', 'write_pubnub_app', 'read_pubnub_resources', 'manage_pubnub_account' ]; for (const toolName in toolDefinitions) { if (toolHandlers[toolName]) { // Skip excluded tools when in chat SDK mode if (chatSdkMode && chatSdkExcludedTools.includes(toolName)) { continue; } // Special handling for chat SDK docs tool if (toolName === 'read_pubnub_chat_sdk_docs' && (chatSdkLanguages.length === 0 || chatSdkTopics.length === 0)) { continue; // Skip this tool if chat SDK data isn't loaded } const toolDef = toolDefinitions[toolName]; serverInstance.tool( toolDef.name, toolDef.description, toolDef.parameters, wrapToolHandler(toolHandlers[toolName], toolName) ); } } }
  • Supporting constants (managementSubjects, managementActions) and helper functions (authenticateWithPubNub, makeAuthenticatedRequest) used exclusively by the manage_pubnub_account handler for Admin API authentication and requests.
    const managementSubjects = ['app', 'api_key']; const managementActions = ['create', 'list', 'delete']; let sessionToken = null; let accountId = null; // Helper function to authenticate with PubNub Admin API async function authenticateWithPubNub() { const email = process.env.PUBNUB_EMAIL; const password = process.env.PUBNUB_PASSWORD; if (!email || !password) { throw new Error('PUBNUB_EMAIL and PUBNUB_PASSWORD environment variables must be set'); } try { const response = await fetch('https://admin.pubnub.com/api/me', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email, password }), }); if (!response.ok) { throw new Error(`Authentication failed: ${response.status} ${response.statusText}`); } const data = await response.json(); sessionToken = data.result.token; accountId = data.result.user.account_id; return { sessionToken, accountId }; } catch (err) { throw new Error(`Authentication error: ${err.message}`); } } // Helper function to make authenticated API calls with retry async function makeAuthenticatedRequest(url, options = {}) { if (!sessionToken) { await authenticateWithPubNub(); } const requestOptions = { ...options, headers: { ...options.headers, 'X-Session-Token': sessionToken, }, }; let response = await fetch(url, requestOptions); // Retry with re-authentication if session expired if (response.status === 401 || response.status === 403) { await authenticateWithPubNub(); requestOptions.headers['X-Session-Token'] = sessionToken; response = await fetch(url, requestOptions); } return response; }
  • index.js:1397-1397 (registration)
    Explicit call to register all tools (including manage_pubnub_account unless in chat-sdk mode) on the main McpServer instance.
    registerAllTools(server, isChatSdkMode);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pubnub/pubnub-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server