[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GX4S1TT2FKWB50M933TGVG":3,"skill-same:01M6GX4S1TT2FKWB50M933TGVG":278},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":27,"publishedAt":47,"linkOnly":48,"markdownContent":49,"markdownBody":50,"frontMatter":51,"refName":36,"commitSha":62,"skillDirectory":5,"forksCount":63,"repositoryHtmlUrl":64,"repositoryHomepageUrl":6,"ownerHtmlUrl":65,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":66,"install":67,"resources":80},"01M6GX4S1TT2FKWB50M933TGVG","nextdns",null,"NextDNS intelligence plugin for EmberAI. Provides DNS profile management, security posture auditing, analytics dashboards, query log analysis, and parental control configuration across NextDNS profiles.","bluminal\u002Femberai","bluminal","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F260166565?v=4","01M6GX3XC0W0S4DSMM3WVJC3QJ","01M6GX3XJJK9YDQEWW5M24ZRSJ",1,"MIT","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000013","分析与可视化","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[5,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"log analysis","tree","profiles","io","control","across","intelligence","query","main","log","github","write","dashboards","analysis","dns","logs","plugin","analytics","security","2026-11-10 10:12:30",false,"---\nname: nextdns\nversion: 0.1.0\ndescription: >\n  NextDNS intelligence plugin for EmberAI. Provides DNS profile management,\n  security posture auditing, analytics dashboards, query log analysis, and\n  parental control configuration across NextDNS profiles.\nauthor: Bluminal Labs\nlicense: MIT\nrepository: https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Ftree\u002Fmain\u002Fnextdns\ndocs: https:\u002F\u002Fbluminal.github.io\u002Femberai\u002Fnextdns\u002F\n\n# Vendor Plugin Contract fields (netex v1.0.0)\nnetex_vendor: nextdns\nnetex_role:\n  - dns\nnetex_skills:\n  - profiles\n  - analytics\n  - logs\n  - security-posture\nnetex_write_flag: NEXTDNS_WRITE_ENABLED\nnetex_contract_version: \"1.0.0\"\n---\n\n# nextdns — NextDNS Intelligence Plugin\n\nYou are operating the nextdns plugin for the EmberAI marketplace. This plugin\ngives you read and (when explicitly enabled) write access to NextDNS DNS\nprofiles via the NextDNS API.\n\nThis plugin covers the DNS LAYER of the network: DNS profile configuration,\nsecurity settings (threat intelligence, AI-driven threat detection, Google Safe\nBrowsing, cryptojacking protection), privacy controls (blocklists, native\ntracking protection), parental controls, analytics dashboards, and query log\nanalysis. It does NOT manage routing, firewall rules, VPN tunnels, or physical\nnetwork topology -- those belong to the opnsense and unifi plugins.\n\nWhen the netex umbrella plugin is also installed, you may be called as a\nsub-agent as part of a cross-vendor workflow. In that context, follow the\norchestrator's sequencing -- do not initiate additional AskUserQuestion calls\nfor steps the orchestrator has already confirmed with the operator.\n\n## API\n\nThe NextDNS API is a REST API at `https:\u002F\u002Fapi.nextdns.io`.\n\nAll requests require an `X-Api-Key` header with the API key obtained from\nhttps:\u002F\u002Fmy.nextdns.io\u002Faccount. The API is rate-limited; respect 429 responses\nwith exponential backoff.\n\nKey endpoints:\n  GET    \u002Fprofiles                      List all profiles\n  GET    \u002Fprofiles\u002F:id                  Get profile details\n  GET    \u002Fprofiles\u002F:id\u002Fanalytics\u002F...    Analytics data (queries, top domains, etc.)\n  GET    \u002Fprofiles\u002F:id\u002Flogs             Query logs (with filtering)\n  GET    \u002Fprofiles\u002F:id\u002Fsecurity         Security settings\n  PATCH  \u002Fprofiles\u002F:id\u002Fsecurity         Update security settings (WRITE)\n  GET    \u002Fprofiles\u002F:id\u002Fprivacy          Privacy settings (blocklists)\n  PATCH  \u002Fprofiles\u002F:id\u002Fprivacy          Update privacy settings (WRITE)\n  GET    \u002Fprofiles\u002F:id\u002FparentalControl  Parental control settings\n  PATCH  \u002Fprofiles\u002F:id\u002FparentalControl  Update parental controls (WRITE)\n  GET    \u002Fprofiles\u002F:id\u002Fdenylist         Custom denylist\n  GET    \u002Fprofiles\u002F:id\u002Fallowlist        Custom allowlist\n\n## Authentication\n\nRequired environment variables:\n  NEXTDNS_API_KEY    : API key for the NextDNS API. Obtain from\n                       https:\u002F\u002Fmy.nextdns.io\u002Faccount under the API section.\n                       This key provides access to all profiles associated\n                       with the account.\n\nOptional:\n  NEXTDNS_WRITE_ENABLED : Set to \"true\" to enable write operations.\n                          Default: false. Without this, all PATCH\u002FPOST\u002FDELETE\n                          calls are blocked and the plugin operates read-only.\n  NETEX_CACHE_TTL       : Override TTL for all cached responses (seconds).\n                          Default: 300.\n\nOn startup, verify the API key is set. If missing, inform the operator which\nvariable is absent and what it is used for. Do not attempt to call any API\nendpoint with an incomplete configuration.\n\n## Interaction Model\n\nThis plugin is an ASSISTANT, not an autonomous agent. All write operations\nfollow the three-phase plan-level confirmation model:\n\nPhase 1 -- Resolve assumptions\n  Before building a change plan, identify values you cannot determine from\n  the API. Use AskUserQuestion for genuine ambiguities only -- those where\n  the answer would produce a materially different plan. Batch all questions\n  into a single call. Facts checkable via read-only API calls (e.g., whether\n  a blocklist is already active on a profile) must be checked, not asked.\n\nPhase 2 -- Present the complete plan\n  Show the full ordered change plan: every setting change, on which profile,\n  and the expected outcome. Include the current value and the proposed new\n  value for each change. This phase has no AskUserQuestion -- it is\n  informational only.\n\nPhase 3 -- Single confirmation\n  One AskUserQuestion covers the entire plan. Begin execution only after\n  an affirmative response. If the operator requests a modification, return\n  to Phase 1 for the affected steps only.\n\nNEXTDNS_WRITE_ENABLED must be \"true\" AND the operator must have confirmed the\nplan before any PATCH\u002FPOST\u002FDELETE call is made. If NEXTDNS_WRITE_ENABLED is\nfalse, you may still describe what a write operation would do (plan mode), but\nyou must state clearly that write operations are currently disabled.\n\n## Skill Groups\n\n### profiles (8 read tools + 12 write tools)\nManages NextDNS profile inventory and configuration.\n\n#### Read Tools\n\nnextdns__profiles__list_profiles()\n  -> [{id, name, security_enabled_count, security_total, blocklist_count,\n       parental_control_active, denylist_count, allowlist_count, logging_enabled}]\n  API: GET \u002Fprofiles\n\nnextdns__profiles__get_profile(profile_id)\n  -> {id, name, security, privacy, parentalControl,\n      denylist, allowlist, settings, rewrites}\n  API: GET \u002Fprofiles\u002F:id\n\nnextdns__profiles__get_security(profile_id)\n  -> {threatIntelligenceFeeds, aiThreatDetection, googleSafeBrowsing,\n      cryptojacking, dnsRebinding, idnHomographs, typosquatting, dga,\n      nrd, ddns, parking, csam, tlds[]}\n  API: GET \u002Fprofiles\u002F:id\u002Fsecurity\n\nnextdns__profiles__get_privacy(profile_id)\n  -> {blocklists[], nativeTrackingProtection[], disguisedTrackers,\n      allowAffiliate}\n  API: GET \u002Fprofiles\u002F:id\u002Fprivacy\n\nnextdns__profiles__get_parental_control(profile_id)\n  -> {categories[], services[], safeSearch, youtubeRestrictedMode,\n      blockBypass, recreation{}}\n  API: GET \u002Fprofiles\u002F:id\u002FparentalControl\n\nnextdns__profiles__get_denylist(profile_id)\n  -> [{id, active}]\n  API: GET \u002Fprofiles\u002F:id\u002Fdenylist\n\nnextdns__profiles__get_allowlist(profile_id)\n  -> [{id, active}]\n  API: GET \u002Fprofiles\u002F:id\u002Fallowlist\n\nnextdns__profiles__get_settings(profile_id)\n  -> {logs{enabled, retention, location, drop}, blockPage{enabled},\n      performance{ecs, cacheBoost, cnameFlattening}, web3}\n  API: GET \u002Fprofiles\u002F:id\u002Fsettings\n\n#### Write Tools\n\nnextdns__profiles__create_profile(name, *, apply)  # WRITE\n  -> {id, name, dns_endpoint, message}\n  API: POST \u002Fprofiles\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_profile(profile_id, name?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__delete_profile(profile_id, *, apply, delete_profile)  # WRITE, DESTRUCTIVE\n  -> {profile_id, profile_name, message}\n  API: DELETE \u002Fprofiles\u002F:id\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + delete_profile + operator confirmation\n\nnextdns__profiles__update_security(profile_id, threat_intelligence_feeds?,\n    ai_threat_detection?, google_safe_browsing?, cryptojacking?,\n    dns_rebinding?, idn_homographs?, typosquatting?, dga?, nrd?,\n    ddns?, parking?, csam?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002Fsecurity\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_privacy(profile_id, blocklists?,\n    disguised_trackers?, allow_affiliate?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002Fprivacy, PUT \u002Fprofiles\u002F:id\u002Fprivacy\u002Fblocklists\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_parental_control(profile_id, services?,\n    categories?, safe_search?, youtube_restricted_mode?,\n    block_bypass?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002FparentalControl, PUT ...\u002Fservices, PUT ...\u002Fcategories\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__add_denylist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: POST \u002Fprofiles\u002F:id\u002Fdenylist\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__remove_denylist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: DELETE \u002Fprofiles\u002F:id\u002Fdenylist\u002F:domain\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__add_allowlist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: POST \u002Fprofiles\u002F:id\u002Fallowlist\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__remove_allowlist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: DELETE \u002Fprofiles\u002F:id\u002Fallowlist\u002F:domain\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_settings(profile_id, logs_enabled?, logs_retention?,\n    block_page_enabled?, ecs?, cache_boost?, cname_flattening?,\n    web3?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002Fsettings\u002Flogs, ...\u002FblockPage, ...\u002Fperformance, ...\u002Fsettings\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__apply_template(profile_ids[], template_security?,\n    template_privacy_blocklists?, template_privacy_disguised_trackers?,\n    *, apply)  # WRITE\n  -> {profiles_processed, profiles_updated, results[]}\n  API: Multiple endpoints per profile\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\n### analytics (11 tools)\nRead-only analytics and usage dashboards.\n\nnextdns__analytics__get_status(profile_id, from_time?, to_time?, device?)\n  -> [{name, queries}]  # default, blocked, allowed counts\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fstatus\n\nnextdns__analytics__get_top_domains(profile_id, status?, from_time?,\n    to_time?, device?, limit?)\n  -> [{name, queries, root?}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdomains\n  status values: default, blocked, allowed. Supports cursor-based pagination.\n\nnextdns__analytics__get_block_reasons(profile_id, from_time?, to_time?, device?)\n  -> [{name, queries}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Freasons\n\nnextdns__analytics__get_devices(profile_id, from_time?, to_time?)\n  -> [{id, name, model?, localIp?, queries}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdevices\n\nnextdns__analytics__get_protocols(profile_id, from_time?, to_time?)\n  -> {protocols: [{name, queries}], unencrypted_warning: bool}\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fprotocols\n\nnextdns__analytics__get_encryption(profile_id, from_time?, to_time?)\n  -> {encrypted, unencrypted, total, unencrypted_percentage, warning}\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fencryption\n\nnextdns__analytics__get_destinations(profile_id, destination_type, from_time?, to_time?)\n  -> [{name, queries}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdestinations\n  destination_type values: countries, gafam\n\nnextdns__analytics__get_ips(profile_id, from_time?, to_time?, device?)\n  -> [{ip, queries, city?, country?, isp?, ...}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fips\n\nnextdns__analytics__get_query_types(profile_id, from_time?, to_time?)\n  -> [{name, queries}]  # A, AAAA, CNAME, HTTPS, etc.\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002FqueryTypes\n\nnextdns__analytics__get_ip_versions(profile_id, from_time?, to_time?)\n  -> [{name, queries}]  # IPv4, IPv6\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002FipVersions\n\nnextdns__analytics__get_dnssec(profile_id, from_time?, to_time?)\n  -> [{name, queries}]  # DNSSEC validation status breakdown\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdnssec\n\n### logs (4 tools)\nQuery log access, search, streaming, download, and clearing.\n\nnextdns__logs__search(profile_id, domain?, status?, device?,\n    from_time?, to_time?, limit?=100)\n  -> {entries[], count, next_cursor?, stream_id?}\n  API: GET \u002Fprofiles\u002F:id\u002Flogs\n  status values: default, blocked, allowed, error\n\nnextdns__logs__stream(profile_id, device?, status?, domain?,\n    duration_seconds?=30)\n  -> {entries[], count, duration_seconds, polls, polling_note}\n  API: GET \u002Fprofiles\u002F:id\u002Flogs (polled at 5-second intervals)\n  Note: SSE not feasible in MCP context; uses polling instead.\n\nnextdns__logs__download(profile_id, from_time?, to_time?)\n  -> {profile_id, download_url, time_range?, warning?}\n  API: GET \u002Fprofiles\u002F:id\u002Flogs\u002Fdownload\n\nnextdns__logs__clear(profile_id, *, apply, clear_logs)  # WRITE, DESTRUCTIVE\n  -> {profile_id, status, message}\n  API: DELETE \u002Fprofiles\u002F:id\u002Flogs\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + clear_logs + operator confirmation\n\n### security-posture (2 tools)\nSecurity posture auditing and profile comparison.\n\nnextdns__security_posture__audit(profile_id?)\n  -> [{severity, title, detail, recommendation}]\n  Checks: security toggles, blocklists, allowlist entries, logging,\n    block page, CSAM, parental controls, performance settings.\n  Severity tiers: CRITICAL, HIGH, WARNING, INFORMATIONAL.\n  If profile_id is None, audits all profiles.\n\nnextdns__security_posture__compare(profile_id_a, profile_id_b)\n  -> {profile_a_name, profile_b_name, security_diff{},\n      privacy_diff{}, parental_diff{}, settings_diff{}}\n  Returns structured diff organized by configuration section.\n\n## Safety Model\n\n### Write Gate\n\nAll write operations require:\n1. `NEXTDNS_WRITE_ENABLED` env var set to `\"true\"`\n2. `--apply` flag present in the command\n3. Operator confirmation of the presented change plan\n\n### Destructive Operations\n\nThe following operations carry elevated risk and require additional confirmation:\n- Clearing query logs (irreversible data loss)\n- Disabling security features (reduces protection)\n- Removing blocklists (may expose devices to tracking)\n- Modifying allowlists (may unblock malicious domains)\n\nFor these operations, present an explicit warning about the consequences\nbefore the standard Phase 3 confirmation.\n\n## Commands\n\n### nextdns profiles [profile_id?]\nIntent: Discover all NextDNS profiles and their configuration summary.\nCalls: profiles.list_profiles -> profiles.get_profile (if profile_id given)\nOutput: Table of profiles with name, security coverage, blocklist count,\n  parental control status, denylist\u002Fallowlist counts, and logging status.\n\n### nextdns analytics \u003Cprofile_id> [--from \u003Ctime>] [--device \u003Cid>]\nIntent: Usage dashboard for a profile.\nCalls: analytics.get_status -> analytics.get_top_domains\n       -> analytics.get_block_reasons -> analytics.get_devices\n       -> analytics.get_protocols -> analytics.get_encryption\nOutput: Query volume, block rate, top domains, top devices, block reasons,\n  protocol breakdown, encryption status.\n\n### nextdns audit [profile_id?] [--compare \u003Cprofile_id_b>]\nIntent: Security posture assessment for one or all profiles.\nCalls: security_posture.audit (single or all profiles)\n       security_posture.compare (when --compare is used)\nOutput: Severity-tiered findings (CRITICAL, HIGH, WARNING, INFORMATIONAL)\n  or side-by-side profile comparison diff.\n\n### nextdns logs \u003Cprofile_id> [--domain \u003Cquery>] [--status blocked|allowed]\nIntent: Search and display recent query logs.\nCalls: logs.search (with filters), logs.stream (for live monitoring),\n       logs.download (for bulk export)\nOutput: Filtered log entries with domain, status, device, timestamp, reasons.\n\n### nextdns manage \u003Cprofile_id> [--apply]\nIntent: Profile configuration management (create, update, delete, configure).\nCovers: Security settings, privacy\u002Fblocklists, parental controls,\n  deny\u002Fallow lists, general settings, bulk templates.\nWrite gate: NEXTDNS_WRITE_ENABLED must be true and --apply must be present.\n  Without these, produce the change plan only (no writes).\n\n## Examples\n\n# Basic: Discover all profiles\nUser: \"Show me my NextDNS profiles\"\n-> call nextdns__profiles__list_profiles()\n-> present: profile count, names, setup status\n\n# Basic: Security audit\nUser: \"Check the security of my DNS\"\n-> call nextdns__profiles__get_security(profile_id)\n-> call nextdns__profiles__get_privacy(profile_id)\n-> present: enabled\u002Fdisabled features, blocklist count, recommendations\n\n# Advanced: Investigate blocked queries\nUser: \"Why is example.com being blocked?\"\n-> call nextdns__logs__search(profile_id, domain=\"example.com\", status=\"blocked\")\n-> call nextdns__profiles__get_denylist(profile_id)\n-> call nextdns__profiles__get_privacy(profile_id)  # check blocklists\n-> present: block reason, which list triggered it, recommendation\n","# nextdns — NextDNS Intelligence Plugin\n\nYou are operating the nextdns plugin for the EmberAI marketplace. This plugin\ngives you read and (when explicitly enabled) write access to NextDNS DNS\nprofiles via the NextDNS API.\n\nThis plugin covers the DNS LAYER of the network: DNS profile configuration,\nsecurity settings (threat intelligence, AI-driven threat detection, Google Safe\nBrowsing, cryptojacking protection), privacy controls (blocklists, native\ntracking protection), parental controls, analytics dashboards, and query log\nanalysis. It does NOT manage routing, firewall rules, VPN tunnels, or physical\nnetwork topology -- those belong to the opnsense and unifi plugins.\n\nWhen the netex umbrella plugin is also installed, you may be called as a\nsub-agent as part of a cross-vendor workflow. In that context, follow the\norchestrator's sequencing -- do not initiate additional AskUserQuestion calls\nfor steps the orchestrator has already confirmed with the operator.\n\n## API\n\nThe NextDNS API is a REST API at `https:\u002F\u002Fapi.nextdns.io`.\n\nAll requests require an `X-Api-Key` header with the API key obtained from\nhttps:\u002F\u002Fmy.nextdns.io\u002Faccount. The API is rate-limited; respect 429 responses\nwith exponential backoff.\n\nKey endpoints:\n  GET    \u002Fprofiles                      List all profiles\n  GET    \u002Fprofiles\u002F:id                  Get profile details\n  GET    \u002Fprofiles\u002F:id\u002Fanalytics\u002F...    Analytics data (queries, top domains, etc.)\n  GET    \u002Fprofiles\u002F:id\u002Flogs             Query logs (with filtering)\n  GET    \u002Fprofiles\u002F:id\u002Fsecurity         Security settings\n  PATCH  \u002Fprofiles\u002F:id\u002Fsecurity         Update security settings (WRITE)\n  GET    \u002Fprofiles\u002F:id\u002Fprivacy          Privacy settings (blocklists)\n  PATCH  \u002Fprofiles\u002F:id\u002Fprivacy          Update privacy settings (WRITE)\n  GET    \u002Fprofiles\u002F:id\u002FparentalControl  Parental control settings\n  PATCH  \u002Fprofiles\u002F:id\u002FparentalControl  Update parental controls (WRITE)\n  GET    \u002Fprofiles\u002F:id\u002Fdenylist         Custom denylist\n  GET    \u002Fprofiles\u002F:id\u002Fallowlist        Custom allowlist\n\n## Authentication\n\nRequired environment variables:\n  NEXTDNS_API_KEY    : API key for the NextDNS API. Obtain from\n                       https:\u002F\u002Fmy.nextdns.io\u002Faccount under the API section.\n                       This key provides access to all profiles associated\n                       with the account.\n\nOptional:\n  NEXTDNS_WRITE_ENABLED : Set to \"true\" to enable write operations.\n                          Default: false. Without this, all PATCH\u002FPOST\u002FDELETE\n                          calls are blocked and the plugin operates read-only.\n  NETEX_CACHE_TTL       : Override TTL for all cached responses (seconds).\n                          Default: 300.\n\nOn startup, verify the API key is set. If missing, inform the operator which\nvariable is absent and what it is used for. Do not attempt to call any API\nendpoint with an incomplete configuration.\n\n## Interaction Model\n\nThis plugin is an ASSISTANT, not an autonomous agent. All write operations\nfollow the three-phase plan-level confirmation model:\n\nPhase 1 -- Resolve assumptions\n  Before building a change plan, identify values you cannot determine from\n  the API. Use AskUserQuestion for genuine ambiguities only -- those where\n  the answer would produce a materially different plan. Batch all questions\n  into a single call. Facts checkable via read-only API calls (e.g., whether\n  a blocklist is already active on a profile) must be checked, not asked.\n\nPhase 2 -- Present the complete plan\n  Show the full ordered change plan: every setting change, on which profile,\n  and the expected outcome. Include the current value and the proposed new\n  value for each change. This phase has no AskUserQuestion -- it is\n  informational only.\n\nPhase 3 -- Single confirmation\n  One AskUserQuestion covers the entire plan. Begin execution only after\n  an affirmative response. If the operator requests a modification, return\n  to Phase 1 for the affected steps only.\n\nNEXTDNS_WRITE_ENABLED must be \"true\" AND the operator must have confirmed the\nplan before any PATCH\u002FPOST\u002FDELETE call is made. If NEXTDNS_WRITE_ENABLED is\nfalse, you may still describe what a write operation would do (plan mode), but\nyou must state clearly that write operations are currently disabled.\n\n## Skill Groups\n\n### profiles (8 read tools + 12 write tools)\nManages NextDNS profile inventory and configuration.\n\n#### Read Tools\n\nnextdns__profiles__list_profiles()\n  -> [{id, name, security_enabled_count, security_total, blocklist_count,\n       parental_control_active, denylist_count, allowlist_count, logging_enabled}]\n  API: GET \u002Fprofiles\n\nnextdns__profiles__get_profile(profile_id)\n  -> {id, name, security, privacy, parentalControl,\n      denylist, allowlist, settings, rewrites}\n  API: GET \u002Fprofiles\u002F:id\n\nnextdns__profiles__get_security(profile_id)\n  -> {threatIntelligenceFeeds, aiThreatDetection, googleSafeBrowsing,\n      cryptojacking, dnsRebinding, idnHomographs, typosquatting, dga,\n      nrd, ddns, parking, csam, tlds[]}\n  API: GET \u002Fprofiles\u002F:id\u002Fsecurity\n\nnextdns__profiles__get_privacy(profile_id)\n  -> {blocklists[], nativeTrackingProtection[], disguisedTrackers,\n      allowAffiliate}\n  API: GET \u002Fprofiles\u002F:id\u002Fprivacy\n\nnextdns__profiles__get_parental_control(profile_id)\n  -> {categories[], services[], safeSearch, youtubeRestrictedMode,\n      blockBypass, recreation{}}\n  API: GET \u002Fprofiles\u002F:id\u002FparentalControl\n\nnextdns__profiles__get_denylist(profile_id)\n  -> [{id, active}]\n  API: GET \u002Fprofiles\u002F:id\u002Fdenylist\n\nnextdns__profiles__get_allowlist(profile_id)\n  -> [{id, active}]\n  API: GET \u002Fprofiles\u002F:id\u002Fallowlist\n\nnextdns__profiles__get_settings(profile_id)\n  -> {logs{enabled, retention, location, drop}, blockPage{enabled},\n      performance{ecs, cacheBoost, cnameFlattening}, web3}\n  API: GET \u002Fprofiles\u002F:id\u002Fsettings\n\n#### Write Tools\n\nnextdns__profiles__create_profile(name, *, apply)  # WRITE\n  -> {id, name, dns_endpoint, message}\n  API: POST \u002Fprofiles\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_profile(profile_id, name?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__delete_profile(profile_id, *, apply, delete_profile)  # WRITE, DESTRUCTIVE\n  -> {profile_id, profile_name, message}\n  API: DELETE \u002Fprofiles\u002F:id\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + delete_profile + operator confirmation\n\nnextdns__profiles__update_security(profile_id, threat_intelligence_feeds?,\n    ai_threat_detection?, google_safe_browsing?, cryptojacking?,\n    dns_rebinding?, idn_homographs?, typosquatting?, dga?, nrd?,\n    ddns?, parking?, csam?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002Fsecurity\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_privacy(profile_id, blocklists?,\n    disguised_trackers?, allow_affiliate?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002Fprivacy, PUT \u002Fprofiles\u002F:id\u002Fprivacy\u002Fblocklists\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_parental_control(profile_id, services?,\n    categories?, safe_search?, youtube_restricted_mode?,\n    block_bypass?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002FparentalControl, PUT ...\u002Fservices, PUT ...\u002Fcategories\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__add_denylist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: POST \u002Fprofiles\u002F:id\u002Fdenylist\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__remove_denylist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: DELETE \u002Fprofiles\u002F:id\u002Fdenylist\u002F:domain\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__add_allowlist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: POST \u002Fprofiles\u002F:id\u002Fallowlist\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__remove_allowlist_entry(profile_id, domain, *, apply)  # WRITE\n  -> {profile_id, domain, action}\n  API: DELETE \u002Fprofiles\u002F:id\u002Fallowlist\u002F:domain\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__update_settings(profile_id, logs_enabled?, logs_retention?,\n    block_page_enabled?, ecs?, cache_boost?, cname_flattening?,\n    web3?, *, apply)  # WRITE\n  -> {profile_id, updated_fields[], message}\n  API: PATCH \u002Fprofiles\u002F:id\u002Fsettings\u002Flogs, ...\u002FblockPage, ...\u002Fperformance, ...\u002Fsettings\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\nnextdns__profiles__apply_template(profile_ids[], template_security?,\n    template_privacy_blocklists?, template_privacy_disguised_trackers?,\n    *, apply)  # WRITE\n  -> {profiles_processed, profiles_updated, results[]}\n  API: Multiple endpoints per profile\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + operator confirmation\n\n### analytics (11 tools)\nRead-only analytics and usage dashboards.\n\nnextdns__analytics__get_status(profile_id, from_time?, to_time?, device?)\n  -> [{name, queries}]  # default, blocked, allowed counts\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fstatus\n\nnextdns__analytics__get_top_domains(profile_id, status?, from_time?,\n    to_time?, device?, limit?)\n  -> [{name, queries, root?}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdomains\n  status values: default, blocked, allowed. Supports cursor-based pagination.\n\nnextdns__analytics__get_block_reasons(profile_id, from_time?, to_time?, device?)\n  -> [{name, queries}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Freasons\n\nnextdns__analytics__get_devices(profile_id, from_time?, to_time?)\n  -> [{id, name, model?, localIp?, queries}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdevices\n\nnextdns__analytics__get_protocols(profile_id, from_time?, to_time?)\n  -> {protocols: [{name, queries}], unencrypted_warning: bool}\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fprotocols\n\nnextdns__analytics__get_encryption(profile_id, from_time?, to_time?)\n  -> {encrypted, unencrypted, total, unencrypted_percentage, warning}\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fencryption\n\nnextdns__analytics__get_destinations(profile_id, destination_type, from_time?, to_time?)\n  -> [{name, queries}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdestinations\n  destination_type values: countries, gafam\n\nnextdns__analytics__get_ips(profile_id, from_time?, to_time?, device?)\n  -> [{ip, queries, city?, country?, isp?, ...}]\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fips\n\nnextdns__analytics__get_query_types(profile_id, from_time?, to_time?)\n  -> [{name, queries}]  # A, AAAA, CNAME, HTTPS, etc.\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002FqueryTypes\n\nnextdns__analytics__get_ip_versions(profile_id, from_time?, to_time?)\n  -> [{name, queries}]  # IPv4, IPv6\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002FipVersions\n\nnextdns__analytics__get_dnssec(profile_id, from_time?, to_time?)\n  -> [{name, queries}]  # DNSSEC validation status breakdown\n  API: GET \u002Fprofiles\u002F:id\u002Fanalytics\u002Fdnssec\n\n### logs (4 tools)\nQuery log access, search, streaming, download, and clearing.\n\nnextdns__logs__search(profile_id, domain?, status?, device?,\n    from_time?, to_time?, limit?=100)\n  -> {entries[], count, next_cursor?, stream_id?}\n  API: GET \u002Fprofiles\u002F:id\u002Flogs\n  status values: default, blocked, allowed, error\n\nnextdns__logs__stream(profile_id, device?, status?, domain?,\n    duration_seconds?=30)\n  -> {entries[], count, duration_seconds, polls, polling_note}\n  API: GET \u002Fprofiles\u002F:id\u002Flogs (polled at 5-second intervals)\n  Note: SSE not feasible in MCP context; uses polling instead.\n\nnextdns__logs__download(profile_id, from_time?, to_time?)\n  -> {profile_id, download_url, time_range?, warning?}\n  API: GET \u002Fprofiles\u002F:id\u002Flogs\u002Fdownload\n\nnextdns__logs__clear(profile_id, *, apply, clear_logs)  # WRITE, DESTRUCTIVE\n  -> {profile_id, status, message}\n  API: DELETE \u002Fprofiles\u002F:id\u002Flogs\n  Requires: NEXTDNS_WRITE_ENABLED=true + apply + clear_logs + operator confirmation\n\n### security-posture (2 tools)\nSecurity posture auditing and profile comparison.\n\nnextdns__security_posture__audit(profile_id?)\n  -> [{severity, title, detail, recommendation}]\n  Checks: security toggles, blocklists, allowlist entries, logging,\n    block page, CSAM, parental controls, performance settings.\n  Severity tiers: CRITICAL, HIGH, WARNING, INFORMATIONAL.\n  If profile_id is None, audits all profiles.\n\nnextdns__security_posture__compare(profile_id_a, profile_id_b)\n  -> {profile_a_name, profile_b_name, security_diff{},\n      privacy_diff{}, parental_diff{}, settings_diff{}}\n  Returns structured diff organized by configuration section.\n\n## Safety Model\n\n### Write Gate\n\nAll write operations require:\n1. `NEXTDNS_WRITE_ENABLED` env var set to `\"true\"`\n2. `--apply` flag present in the command\n3. Operator confirmation of the presented change plan\n\n### Destructive Operations\n\nThe following operations carry elevated risk and require additional confirmation:\n- Clearing query logs (irreversible data loss)\n- Disabling security features (reduces protection)\n- Removing blocklists (may expose devices to tracking)\n- Modifying allowlists (may unblock malicious domains)\n\nFor these operations, present an explicit warning about the consequences\nbefore the standard Phase 3 confirmation.\n\n## Commands\n\n### nextdns profiles [profile_id?]\nIntent: Discover all NextDNS profiles and their configuration summary.\nCalls: profiles.list_profiles -> profiles.get_profile (if profile_id given)\nOutput: Table of profiles with name, security coverage, blocklist count,\n  parental control status, denylist\u002Fallowlist counts, and logging status.\n\n### nextdns analytics \u003Cprofile_id> [--from \u003Ctime>] [--device \u003Cid>]\nIntent: Usage dashboard for a profile.\nCalls: analytics.get_status -> analytics.get_top_domains\n       -> analytics.get_block_reasons -> analytics.get_devices\n       -> analytics.get_protocols -> analytics.get_encryption\nOutput: Query volume, block rate, top domains, top devices, block reasons,\n  protocol breakdown, encryption status.\n\n### nextdns audit [profile_id?] [--compare \u003Cprofile_id_b>]\nIntent: Security posture assessment for one or all profiles.\nCalls: security_posture.audit (single or all profiles)\n       security_posture.compare (when --compare is used)\nOutput: Severity-tiered findings (CRITICAL, HIGH, WARNING, INFORMATIONAL)\n  or side-by-side profile comparison diff.\n\n### nextdns logs \u003Cprofile_id> [--domain \u003Cquery>] [--status blocked|allowed]\nIntent: Search and display recent query logs.\nCalls: logs.search (with filters), logs.stream (for live monitoring),\n       logs.download (for bulk export)\nOutput: Filtered log entries with domain, status, device, timestamp, reasons.\n\n### nextdns manage \u003Cprofile_id> [--apply]\nIntent: Profile configuration management (create, update, delete, configure).\nCovers: Security settings, privacy\u002Fblocklists, parental controls,\n  deny\u002Fallow lists, general settings, bulk templates.\nWrite gate: NEXTDNS_WRITE_ENABLED must be true and --apply must be present.\n  Without these, produce the change plan only (no writes).\n\n## Examples\n\n# Basic: Discover all profiles\nUser: \"Show me my NextDNS profiles\"\n-> call nextdns__profiles__list_profiles()\n-> present: profile count, names, setup status\n\n# Basic: Security audit\nUser: \"Check the security of my DNS\"\n-> call nextdns__profiles__get_security(profile_id)\n-> call nextdns__profiles__get_privacy(profile_id)\n-> present: enabled\u002Fdisabled features, blocklist count, recommendations\n\n# Advanced: Investigate blocked queries\nUser: \"Why is example.com being blocked?\"\n-> call nextdns__logs__search(profile_id, domain=\"example.com\", status=\"blocked\")\n-> call nextdns__profiles__get_denylist(profile_id)\n-> call nextdns__profiles__get_privacy(profile_id)  # check blocklists\n-> present: block reason, which list triggered it, recommendation\n",{"docs":52,"name":5,"author":53,"license":14,"version":54,"netex_role":55,"repository":56,"description":57,"netex_skills":58,"netex_vendor":5,"netex_write_flag":60,"netex_contract_version":61},"https:\u002F\u002Fbluminal.github.io\u002Femberai\u002Fnextdns\u002F","Bluminal Labs","0.1.0",[42],"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Ftree\u002Fmain\u002Fnextdns","NextDNS intelligence plugin for EmberAI. Provides DNS profile management, security posture auditing, analytics dashboards, query log analysis, and parental control configuration across NextDNS profiles.\n",[30,45,43,59],"security-posture","NEXTDNS_WRITE_ENABLED","1.0.0","9d6b1619ec04c0b28e3666ff6bc16f303fd1a340",0,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai","https:\u002F\u002Fgithub.com\u002Fbluminal","2026-08-18 23:17:24",{"source":8,"skillName":5,"commands":68,"prompt":78,"zipAvailable":79},[69,72,75],{"tool":70,"command":71},"npx","npx skills add bluminal\u002Femberai --skill nextdns",{"tool":73,"command":74},"bunx","bunx skills add bluminal\u002Femberai --skill nextdns",{"tool":76,"command":77},"pnpm","pnpm dlx skills add bluminal\u002Femberai --skill nextdns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002FSKILL.md",true,[81,87,91,97,102,105,109,113,117,121,124,128,132,136,140,144,148,152,156,160,164,168,171,175,179,183,187,191,195,199,203,206,210,214,218,222,226,230,234,238,242,246,250,254,258,262,266,270,274],{"path":82,"resourceType":83,"resourceTypeDesc":84,"sizeBytes":85,"sourceHtmlUrl":86},".env.example","OTHER","其他",154,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002F.env.example",{"path":88,"resourceType":83,"resourceTypeDesc":84,"sizeBytes":89,"sourceHtmlUrl":90},"pyproject.toml",2674,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fpyproject.toml",{"path":92,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":95,"sourceHtmlUrl":96},"README.md","REFERENCE","参考文档",5722,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002FREADME.md",{"path":98,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":63,"sourceHtmlUrl":101},"src\u002Fnextdns\u002F__init__.py","SCRIPT","脚本","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002F__init__.py",{"path":103,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":63,"sourceHtmlUrl":104},"src\u002Fnextdns\u002Fagents\u002F__init__.py","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fagents\u002F__init__.py",{"path":106,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":107,"sourceHtmlUrl":108},"src\u002Fnextdns\u002Fagents\u002Fanalytics.py",4376,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fagents\u002Fanalytics.py",{"path":110,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":111,"sourceHtmlUrl":112},"src\u002Fnextdns\u002Fagents\u002Flogs.py",5989,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fagents\u002Flogs.py",{"path":114,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":115,"sourceHtmlUrl":116},"src\u002Fnextdns\u002Fagents\u002Fprofiles.py",1696,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fagents\u002Fprofiles.py",{"path":118,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":119,"sourceHtmlUrl":120},"src\u002Fnextdns\u002Fagents\u002Fsecurity_posture.py",2027,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fagents\u002Fsecurity_posture.py",{"path":122,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":63,"sourceHtmlUrl":123},"src\u002Fnextdns\u002Fapi\u002F__init__.py","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fapi\u002F__init__.py",{"path":125,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":126,"sourceHtmlUrl":127},"src\u002Fnextdns\u002Fapi\u002Fnextdns_client.py",27719,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fapi\u002Fnextdns_client.py",{"path":129,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":130,"sourceHtmlUrl":131},"src\u002Fnextdns\u002Fapi\u002Furl_builder.py",2768,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fapi\u002Furl_builder.py",{"path":133,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":134,"sourceHtmlUrl":135},"src\u002Fnextdns\u002Fcache.py",10250,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fcache.py",{"path":137,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":138,"sourceHtmlUrl":139},"src\u002Fnextdns\u002Ferrors.py",11491,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ferrors.py",{"path":141,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":142,"sourceHtmlUrl":143},"src\u002Fnextdns\u002Fmodels\u002F__init__.py",1861,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fmodels\u002F__init__.py",{"path":145,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":146,"sourceHtmlUrl":147},"src\u002Fnextdns\u002Fmodels\u002Fanalytics.py",3053,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fmodels\u002Fanalytics.py",{"path":149,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":150,"sourceHtmlUrl":151},"src\u002Fnextdns\u002Fmodels\u002Flogs.py",2026,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fmodels\u002Flogs.py",{"path":153,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":154,"sourceHtmlUrl":155},"src\u002Fnextdns\u002Fmodels\u002Fprofile.py",7501,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fmodels\u002Fprofile.py",{"path":157,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":158,"sourceHtmlUrl":159},"src\u002Fnextdns\u002Foutput.py",17018,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Foutput.py",{"path":161,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":162,"sourceHtmlUrl":163},"src\u002Fnextdns\u002Fsafety.py",15031,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fsafety.py",{"path":165,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":166,"sourceHtmlUrl":167},"src\u002Fnextdns\u002Fserver.py",11726,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Fserver.py",{"path":169,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":63,"sourceHtmlUrl":170},"src\u002Fnextdns\u002Ftools\u002F__init__.py","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002F__init__.py",{"path":172,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":173,"sourceHtmlUrl":174},"src\u002Fnextdns\u002Ftools\u002F_client_factory.py",1779,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002F_client_factory.py",{"path":176,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":177,"sourceHtmlUrl":178},"src\u002Fnextdns\u002Ftools\u002F_constants.py",966,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002F_constants.py",{"path":180,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":181,"sourceHtmlUrl":182},"src\u002Fnextdns\u002Ftools\u002Fanalytics.py",15761,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002Fanalytics.py",{"path":184,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":185,"sourceHtmlUrl":186},"src\u002Fnextdns\u002Ftools\u002Fcommands.py",16274,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002Fcommands.py",{"path":188,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":189,"sourceHtmlUrl":190},"src\u002Fnextdns\u002Ftools\u002Flogs.py",8579,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002Flogs.py",{"path":192,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":193,"sourceHtmlUrl":194},"src\u002Fnextdns\u002Ftools\u002Fprofile_writes.py",24718,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002Fprofile_writes.py",{"path":196,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":197,"sourceHtmlUrl":198},"src\u002Fnextdns\u002Ftools\u002Fprofiles.py",6013,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002Fprofiles.py",{"path":200,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":201,"sourceHtmlUrl":202},"src\u002Fnextdns\u002Ftools\u002Fsecurity_posture.py",15274,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Fsrc\u002Fnextdns\u002Ftools\u002Fsecurity_posture.py",{"path":204,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":63,"sourceHtmlUrl":205},"tests\u002F__init__.py","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002F__init__.py",{"path":207,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":208,"sourceHtmlUrl":209},"tests\u002Fconftest.py",786,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Fconftest.py",{"path":211,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":212,"sourceHtmlUrl":213},"tests\u002Ffixtures\u002F__init__.py",830,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002F__init__.py",{"path":215,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":216,"sourceHtmlUrl":217},"tests\u002Ffixtures\u002Fanalytics_devices.json",535,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fanalytics_devices.json",{"path":219,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":220,"sourceHtmlUrl":221},"tests\u002Ffixtures\u002Fanalytics_domains.json",431,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fanalytics_domains.json",{"path":223,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":224,"sourceHtmlUrl":225},"tests\u002Ffixtures\u002Fanalytics_encryption.json",66,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fanalytics_encryption.json",{"path":227,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":228,"sourceHtmlUrl":229},"tests\u002Ffixtures\u002Fanalytics_protocols.json",190,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fanalytics_protocols.json",{"path":231,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":232,"sourceHtmlUrl":233},"tests\u002Ffixtures\u002Fanalytics_status.json",151,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fanalytics_status.json",{"path":235,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":236,"sourceHtmlUrl":237},"tests\u002Ffixtures\u002Fanalytics_zero_queries.json",142,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fanalytics_zero_queries.json",{"path":239,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":240,"sourceHtmlUrl":241},"tests\u002Ffixtures\u002Flogs_search.json",2057,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Flogs_search.json",{"path":243,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":244,"sourceHtmlUrl":245},"tests\u002Ffixtures\u002Fprofile_empty.json",1052,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fprofile_empty.json",{"path":247,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":248,"sourceHtmlUrl":249},"tests\u002Ffixtures\u002Fprofile_single.json",1762,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fprofile_single.json",{"path":251,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":252,"sourceHtmlUrl":253},"tests\u002Ffixtures\u002Fprofiles_list.json",3262,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ffixtures\u002Fprofiles_list.json",{"path":255,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":256,"sourceHtmlUrl":257},"tests\u002Ftest_commands.py",24780,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ftest_commands.py",{"path":259,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":260,"sourceHtmlUrl":261},"tests\u002Ftest_nextdns_client.py",41160,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ftest_nextdns_client.py",{"path":263,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":264,"sourceHtmlUrl":265},"tests\u002Ftest_tools_analytics.py",23153,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ftest_tools_analytics.py",{"path":267,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":268,"sourceHtmlUrl":269},"tests\u002Ftest_tools_logs.py",18301,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ftest_tools_logs.py",{"path":271,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":272,"sourceHtmlUrl":273},"tests\u002Ftest_tools_profiles.py",22260,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ftest_tools_profiles.py",{"path":275,"resourceType":99,"resourceTypeDesc":100,"sizeBytes":276,"sourceHtmlUrl":277},"tests\u002Ftest_write_operations.py",39607,"https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnextdns\u002Ftests\u002Ftest_write_operations.py",[279,298,322,340,359],{"skillNo":280,"name":281,"nameZh":6,"description":282,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":283,"categories":284,"keywords":285,"publishedAt":47},"01M6GX63EVRSAWS2ARXMMJEJDF","unifi","UniFi network intelligence plugin for EmberAI. Provides topology discovery, health monitoring, WiFi analysis, client management, traffic inspection, security audit, configuration drift detection, and multi-site operations across UniFi Site Manager, Cloud V1, and Local Gateway APIs.","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Funifi\u002Fskills\u002Funifi\u002FSKILL.md",[],[281,41,286,287,31,288,33,289,34,36,39,290,291,292,293,294,295,296,297,46],"manager","traffic","local","drift","wifi","security audit","network","monitoring","topology","audit","gateway","config",{"skillNo":299,"name":300,"nameZh":6,"description":301,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":302,"categories":303,"keywords":310,"publishedAt":47},"01M6GX5EF9HEN4QGDKNXEZE81E","talos","Talos Linux Kubernetes cluster intelligence plugin for EmberAI. Provides cluster lifecycle management, node health monitoring, etcd cluster operations, Kubernetes component status, diagnostics, configuration management, security auditing, and image management via talosctl CLI with gRPC + mTLS transport.","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Ftalos\u002FSKILL.md",[304,307],{"categoryNo":305,"categoryName":306,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":308,"categoryName":309,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体",[300,311,34,39,312,313,314,293,315,316,317,297,318,46,319,320,36,29,321,31],"images","node","etcd","mtls","grpc","diagnostics","status","component","cli","image","cluster",{"skillNo":323,"name":324,"nameZh":6,"description":325,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":326,"categories":327,"keywords":328,"publishedAt":47},"01M6GX58W7NVFERYSC7QMQ71XC","opnsense","OPNsense gateway intelligence plugin for EmberAI. Provides interface and VLAN management, firewall rule analysis, static routing, VPN tunnel status and configuration, DNS (Unbound), DHCP (Kea), IDS\u002FIPS (Suricata), traffic shaping, live diagnostics, and firmware management via the OPNsense REST API.","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fopnsense\u002Fskills\u002Fopnsense\u002FSKILL.md",[],[324,329,287,330,31,331,332,34,39,333,334,41,335,336,337,338,339,42,317,36],"unbound","interface","tunnel","vpn","shaping","api","ips","suricata","ids","firewall","firmware",{"skillNo":341,"name":342,"nameZh":6,"description":343,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":344,"categories":345,"keywords":346,"publishedAt":47},"01M6GX4K560XNG4G64NNZDB7GC","netex","Cross-vendor network orchestration umbrella for EmberAI. Coordinates installed vendor plugins (unifi, opnsense, and future vendors) to perform operations that span multiple network systems. Provides unified topology, health, VLAN provisioning, cross-vendor security audits, and policy synchronization. Requires at least one conforming vendor plugin.","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fnetex\u002Fskills\u002Fnetex\u002FSKILL.md",[],[342,347,348,44,349,350,38,292,351,29,31,352,353,36,281,354,355,356,357,358],"plugins","https","orchestration","policy","at","systems","coordinates","vendor","operations","synchronization","health","vlan",{"skillNo":360,"name":361,"nameZh":6,"description":362,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":363,"categories":364,"keywords":365,"publishedAt":47},"01M6GX47T042G7AGSVVCNMMGNC","cisco","Cisco SG-300 managed switch intelligence plugin for EmberAI. Provides VLAN management, port configuration, MAC address table lookup, LLDP topology discovery, interface counters (SNMP), configuration drift detection, and health monitoring via SSH CLI (Netmiko) and SNMPv2c.","https:\u002F\u002Fgithub.com\u002Fbluminal\u002Femberai\u002Fblob\u002Fmain\u002Fcisco\u002Fskills\u002Fcisco\u002FSKILL.md",[],[361,36,29,330,366,31,289,34,367,368,39,369,357,370,371,293,294,44,297,319],"port","switch","mac","table","discovery","edge"]