manage_credentials
Securely store, check, or remove New Relic API credentials in your system's keychain to enable programmatic access to monitoring data.
Instructions
Manage New Relic credentials securely in keychain.
Actions:
- 'status': Show current credential status
- 'store': Store new credentials (requires api_key parameter)
- 'delete': Remove all credentials from keychain
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| api_key | No | ||
| account_id | No |
Implementation Reference
- newrelic_mcp/server.py:549-617 (handler)Core implementation of the manage_credentials tool handler. Includes @mcp.tool() registration decorator, function signature serving as input schema, and full logic for managing credentials via SecureCredentials.@mcp.tool() async def manage_credentials( action: str, api_key: Optional[str] = None, account_id: Optional[str] = None ) -> str: """ Manage New Relic credentials securely in keychain. Actions: - 'status': Show current credential status - 'store': Store new credentials (requires api_key parameter) - 'delete': Remove all credentials from keychain """ try: if action == "status": status = SecureCredentials.list_stored_credentials() return json.dumps( {"status": status, "message": "Current credential status"}, indent=2 ) elif action == "store": if not api_key: return json.dumps( {"error": "api_key parameter is required for store action"}, indent=2, ) if not api_key.startswith("NRAK-"): return json.dumps( { "error": "Invalid API key format. " "New Relic API keys start with 'NRAK-'" }, indent=2, ) SecureCredentials.store_api_key(api_key) if account_id: SecureCredentials.store_account_id(account_id) return json.dumps( { "success": True, "message": "Credentials stored securely in keychain", }, indent=2, ) elif action == "delete": SecureCredentials.delete_credentials() return json.dumps( { "success": True, "message": "All credentials removed from keychain", }, indent=2, ) else: return json.dumps( { "error": f"Unknown action '{action}'. " "Valid actions: status, store, delete" }, indent=2, ) except Exception as e: return json.dumps({"error": str(e)}, indent=2)
- newrelic_mcp/credentials.py:17-132 (helper)Supporting SecureCredentials class with static methods for storing, retrieving, listing, and deleting New Relic API keys and account IDs using macOS Keychain (keyring library). Directly called by the manage_credentials handler.class SecureCredentials: """Secure credential storage using macOS Keychain""" @staticmethod def store_api_key(api_key: str) -> None: """Store New Relic API key securely in keychain""" try: keyring.set_password(SERVICE_NAME, "api_key", api_key) logger.info("API key stored securely in keychain") except Exception as e: logger.error(f"Failed to store API key in keychain: {e}") raise @staticmethod def get_api_key() -> Optional[str]: """Retrieve New Relic API key from keychain or environment""" # First try keychain try: api_key = keyring.get_password(SERVICE_NAME, "api_key") if api_key: logger.info("Retrieved API key from keychain") return api_key except Exception as e: logger.warning(f"Failed to retrieve API key from keychain: {e}") # Fallback to environment variables for backwards compatibility api_key = os.getenv("NEWRELIC_API_KEY") or os.getenv("NEW_RELIC_API_KEY") if api_key: logger.warning( "Using API key from environment variable " "(consider migrating to keychain)" ) return api_key @staticmethod def store_account_id(account_id: str) -> None: """Store New Relic account ID securely in keychain""" try: keyring.set_password(SERVICE_NAME, "account_id", account_id) logger.info("Account ID stored securely in keychain") except Exception as e: logger.error(f"Failed to store account ID in keychain: {e}") raise @staticmethod def get_account_id() -> Optional[str]: """Retrieve New Relic account ID from keychain or environment""" # First try keychain try: account_id = keyring.get_password(SERVICE_NAME, "account_id") if account_id: logger.info("Retrieved account ID from keychain") return account_id except Exception as e: logger.warning(f"Failed to retrieve account ID from keychain: {e}") # Fallback to environment variable for backwards compatibility account_id = os.getenv("NEWRELIC_ACCOUNT_ID") if account_id: logger.warning( "Using account ID from environment variable " "(consider migrating to keychain)" ) return account_id @staticmethod def get_region() -> str: """Get New Relic region (stored as env var as it's not sensitive)""" return os.getenv("NEWRELIC_REGION", "US") @staticmethod def delete_credentials() -> None: """Remove all stored credentials from keychain""" try: keyring.delete_password(SERVICE_NAME, "api_key") logger.info("API key removed from keychain") except keyring.errors.PasswordDeleteError: logger.info("No API key found in keychain to delete") except Exception as e: logger.error(f"Failed to delete API key from keychain: {e}") try: keyring.delete_password(SERVICE_NAME, "account_id") logger.info("Account ID removed from keychain") except keyring.errors.PasswordDeleteError: logger.info("No account ID found in keychain to delete") except Exception as e: logger.error(f"Failed to delete account ID from keychain: {e}") @staticmethod def list_stored_credentials() -> dict: """List what credentials are stored (True/False, not actual values)""" credentials = {} try: api_key = keyring.get_password(SERVICE_NAME, "api_key") credentials["api_key_in_keychain"] = api_key is not None except Exception: credentials["api_key_in_keychain"] = False try: account_id = keyring.get_password(SERVICE_NAME, "account_id") credentials["account_id_in_keychain"] = account_id is not None except Exception: credentials["account_id_in_keychain"] = False credentials["api_key_in_env"] = bool( os.getenv("NEWRELIC_API_KEY") or os.getenv("NEW_RELIC_API_KEY") ) credentials["account_id_in_env"] = bool(os.getenv("NEWRELIC_ACCOUNT_ID")) credentials["region"] = os.getenv("NEWRELIC_REGION", "US") return credentials