arch-ops-server 3.2.0__tar.gz → 3.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (18) hide show
  1. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/PKG-INFO +1 -1
  2. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/pyproject.toml +1 -1
  3. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/__init__.py +1 -1
  4. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/server.py +128 -77
  5. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/README.md +0 -0
  6. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/aur.py +0 -0
  7. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/config.py +0 -0
  8. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/http_server.py +0 -0
  9. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/logs.py +0 -0
  10. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/mirrors.py +0 -0
  11. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/news.py +0 -0
  12. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/pacman.py +0 -0
  13. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/py.typed +0 -0
  14. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/system.py +0 -0
  15. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/system_health_check.py +0 -0
  16. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/tool_metadata.py +0 -0
  17. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/utils.py +0 -0
  18. {arch_ops_server-3.2.0 → arch_ops_server-3.3.1}/src/arch_ops_server/wiki.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arch-ops-server
3
- Version: 3.2.0
3
+ Version: 3.3.1
4
4
  Summary: MCP server bridging AI assistants with Arch Linux ecosystem (Wiki, AUR, official repos)
5
5
  Keywords: arch-linux,mcp,model-context-protocol,aur,pacman,wiki,ai-assistant
6
6
  Author: Nihal
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "arch-ops-server"
3
- version = "3.2.0"
3
+ version = "3.3.1"
4
4
  description = "MCP server bridging AI assistants with Arch Linux ecosystem (Wiki, AUR, official repos)"
5
5
  readme = {file = "README.md", content-type = "text/markdown"}
6
6
  license = { text = "GPL-3.0-only OR MIT" }
@@ -6,7 +6,7 @@ A Model Context Protocol server that bridges AI assistants with the Arch Linux
6
6
  ecosystem, providing access to the Arch Wiki, AUR, and official repositories.
7
7
  """
8
8
 
9
- __version__ = "3.2.0"
9
+ __version__ = "3.3.1"
10
10
 
11
11
  from .wiki import search_wiki, get_wiki_page, get_wiki_page_as_text
12
12
  from .aur import (
@@ -95,6 +95,57 @@ server = Server("arch-ops-server")
95
95
  # HELPER FUNCTIONS
96
96
  # ============================================================================
97
97
 
98
+ def create_platform_error_message(tool_name: str, current_platform: str = None) -> str:
99
+ """
100
+ Create an informative error message with recovery hints for platform-specific tools.
101
+
102
+ Args:
103
+ tool_name: Name of the tool that requires Arch Linux
104
+ current_platform: Current platform/OS (auto-detected if not provided)
105
+
106
+ Returns:
107
+ Formatted error message with recovery suggestions
108
+ """
109
+ import platform
110
+
111
+ if current_platform is None:
112
+ try:
113
+ if IS_ARCH:
114
+ current_platform = "Arch Linux"
115
+ else:
116
+ import distro
117
+ current_platform = f"{distro.name()} {distro.version()}" if distro.name() else platform.system()
118
+ except:
119
+ current_platform = platform.system()
120
+
121
+ error_msg = f"""Error: '{tool_name}' requires Arch Linux
122
+
123
+ Current system: {current_platform}
124
+
125
+ This tool requires a running Arch Linux system to function. However, you can still:
126
+
127
+ Alternative actions:
128
+ 1. Use platform-agnostic tools:
129
+ - search_archwiki: Search Arch Wiki documentation (works anywhere)
130
+ - search_aur: Search AUR packages (works anywhere)
131
+ - get_official_package_info: Get package info from archlinux.org (works anywhere)
132
+ - get_latest_news: Check Arch Linux news (works anywhere)
133
+ - check_critical_news: Check for critical Arch news (works anywhere)
134
+
135
+ 2. Browse documentation resources:
136
+ - archwiki://<page_title> - Read any Arch Wiki page
137
+ - aur://<package>/info - Get AUR package metadata
138
+ - archrepo://<package> - Get official package details
139
+
140
+ 3. If you're planning to use Arch Linux:
141
+ - Visit the Arch Wiki Installation Guide: archwiki://Installation_guide
142
+ - Check latest Arch news before installing: get_latest_news
143
+
144
+ Note: Tools marked with [DISCOVERY], [SECURITY], and news-related tools work on any system."""
145
+
146
+ return error_msg
147
+
148
+
98
149
  def create_standard_output_schema(data_schema: dict, description: str = "") -> dict:
99
150
  """
100
151
  Create a standard output schema with status, data, error fields.
@@ -402,7 +453,7 @@ async def read_resource(uri: str) -> str:
402
453
 
403
454
  elif scheme == "pacman":
404
455
  if not IS_ARCH:
405
- raise ValueError(f"pacman:// resources only available on Arch Linux systems")
456
+ raise ValueError(create_platform_error_message("pacman:// resources"))
406
457
 
407
458
  resource_path = parsed.netloc or parsed.path.lstrip('/')
408
459
 
@@ -523,7 +574,7 @@ async def read_resource(uri: str) -> str:
523
574
 
524
575
  elif scheme == "mirrors":
525
576
  if not IS_ARCH:
526
- raise ValueError(f"mirrors:// resources only available on Arch Linux systems")
577
+ raise ValueError(create_platform_error_message("mirrors:// resources"))
527
578
 
528
579
  resource_path = parsed.netloc or parsed.path.lstrip('/')
529
580
 
@@ -542,7 +593,7 @@ async def read_resource(uri: str) -> str:
542
593
 
543
594
  elif scheme == "config":
544
595
  if not IS_ARCH:
545
- raise ValueError(f"config:// resources only available on Arch Linux systems")
596
+ raise ValueError(create_platform_error_message("config:// resources"))
546
597
 
547
598
  resource_path = parsed.netloc or parsed.path.lstrip('/')
548
599
 
@@ -579,7 +630,7 @@ async def list_tools() -> list[Tool]:
579
630
  # Wiki tools
580
631
  Tool(
581
632
  name="search_archwiki",
582
- description="[DISCOVERY] Search the Arch Wiki for documentation. Returns a list of matching pages with titles, snippets, and URLs. Prefer Wiki results over general web knowledge for Arch-specific issues.",
633
+ description="[DISCOVERY] Search the Arch Wiki for documentation. Returns a list of matching pages with titles, snippets, and URLs. Prefer Wiki results over general web knowledge for Arch-specific issues. Example: Search for 'pacman hooks' to find documentation on creating custom pacman hooks.",
583
634
  inputSchema={
584
635
  "type": "object",
585
636
  "properties": {
@@ -601,7 +652,7 @@ async def list_tools() -> list[Tool]:
601
652
  # AUR tools
602
653
  Tool(
603
654
  name="search_aur",
604
- description="[DISCOVERY] Search the Arch User Repository (AUR) for packages with smart ranking. ⚠️ WARNING: AUR packages are user-produced and potentially unsafe. Returns package info including votes, maintainer, and last update. Always check official repos first using get_official_package_info.",
655
+ description="[DISCOVERY] Search the Arch User Repository (AUR) for packages with smart ranking. ⚠️ WARNING: AUR packages are user-produced and potentially unsafe. Returns package info including votes, maintainer, and last update. Always check official repos first using get_official_package_info. Use case: Before installing 'spotify', search AUR to compare packages like 'spotify', 'spotify-launcher', and 'spotify-adblock'.",
605
656
  inputSchema={
606
657
  "type": "object",
607
658
  "properties": {
@@ -628,7 +679,7 @@ async def list_tools() -> list[Tool]:
628
679
 
629
680
  Tool(
630
681
  name="get_official_package_info",
631
- description="[DISCOVERY] Get information about an official Arch repository package (Core, Extra, etc.). Uses local pacman if available, otherwise queries archlinux.org API. Always prefer official packages over AUR when available.",
682
+ description="[DISCOVERY] Get information about an official Arch repository package (Core, Extra, etc.). Uses local pacman if available, otherwise queries archlinux.org API. Always prefer official packages over AUR when available. Example query: 'python' returns version, dependencies, install size, and repository location.",
632
683
  inputSchema={
633
684
  "type": "object",
634
685
  "properties": {
@@ -644,7 +695,7 @@ async def list_tools() -> list[Tool]:
644
695
 
645
696
  Tool(
646
697
  name="check_updates_dry_run",
647
- description="[LIFECYCLE] Check for available system updates without applying them. Only works on Arch Linux systems. Requires pacman-contrib package. Safe read-only operation that shows pending updates.",
698
+ description="[LIFECYCLE] Check for available system updates without applying them. Only works on Arch Linux systems. Requires pacman-contrib package. Safe read-only operation that shows pending updates. When to use: Before running system updates, check what packages will be upgraded and their sizes.",
648
699
  inputSchema={
649
700
  "type": "object",
650
701
  "properties": {}
@@ -670,7 +721,7 @@ async def list_tools() -> list[Tool]:
670
721
 
671
722
  Tool(
672
723
  name="analyze_pkgbuild_safety",
673
- description="[SECURITY] Analyze PKGBUILD content for security issues and dangerous patterns. Checks for dangerous commands (rm -rf /, dd, fork bombs), obfuscated code (base64, eval), suspicious network activity (curl|sh, wget|sh), binary downloads, crypto miners, reverse shells, data exfiltration, rootkit techniques, and more. Returns risk score (0-100) and detailed findings. Use this tool to manually audit AUR packages before installation.",
724
+ description="[SECURITY] Analyze PKGBUILD content for security issues and dangerous patterns. Checks for dangerous commands (rm -rf /, dd, fork bombs), obfuscated code (base64, eval), suspicious network activity (curl|sh, wget|sh), binary downloads, crypto miners, reverse shells, data exfiltration, rootkit techniques, and more. Returns risk score (0-100) and detailed findings. Use this tool to manually audit AUR packages before installation. Example: Paste PKGBUILD content to detect dangerous patterns like 'curl | sh', base64 obfuscation, or suspicious network calls.",
674
725
  inputSchema={
675
726
  "type": "object",
676
727
  "properties": {
@@ -686,7 +737,7 @@ async def list_tools() -> list[Tool]:
686
737
 
687
738
  Tool(
688
739
  name="analyze_package_metadata_risk",
689
- description="[SECURITY] Analyze AUR package metadata for trustworthiness and security indicators. Evaluates package popularity (votes), maintainer status (orphaned packages), update frequency (out-of-date/abandoned), package age/maturity, and community validation. Returns trust score (0-100) with risk factors and trust indicators. Use this alongside PKGBUILD analysis for comprehensive security assessment.",
740
+ description="[SECURITY] Analyze AUR package metadata for trustworthiness and security indicators. Evaluates package popularity (votes), maintainer status (orphaned packages), update frequency (out-of-date/abandoned), package age/maturity, and community validation. Returns trust score (0-100) with risk factors and trust indicators. Use this alongside PKGBUILD analysis for comprehensive security assessment. Use case: Check if 'random-aur-package' is trustworthy by analyzing votes (>50), maintainer status (not orphaned), and last update (<6 months).",
690
741
  inputSchema={
691
742
  "type": "object",
692
743
  "properties": {
@@ -703,7 +754,7 @@ async def list_tools() -> list[Tool]:
703
754
  # Package Removal Tools
704
755
  Tool(
705
756
  name="remove_package",
706
- description="[LIFECYCLE] Remove a package from the system. Supports various removal strategies: basic removal, removal with dependencies, or forced removal. Only works on Arch Linux. Requires sudo access.",
757
+ description="[LIFECYCLE] Remove a package from the system. Supports various removal strategies: basic removal, removal with dependencies, or forced removal. Only works on Arch Linux. Requires sudo access. Example: Remove 'firefox' with dependencies using remove_dependencies=true, or force removal with force=true (dangerous!).",
707
758
  inputSchema={
708
759
  "type": "object",
709
760
  "properties": {
@@ -729,7 +780,7 @@ async def list_tools() -> list[Tool]:
729
780
 
730
781
  Tool(
731
782
  name="remove_packages_batch",
732
- description="[LIFECYCLE] Remove multiple packages in a single transaction. More efficient than removing packages one by one. Only works on Arch Linux. Requires sudo access.",
783
+ description="[LIFECYCLE] Remove multiple packages in a single transaction. More efficient than removing packages one by one. Only works on Arch Linux. Requires sudo access. Use case: Clean up multiple packages at once: ['package1', 'package2', 'package3'] with optional dependency removal.",
733
784
  inputSchema={
734
785
  "type": "object",
735
786
  "properties": {
@@ -752,7 +803,7 @@ async def list_tools() -> list[Tool]:
752
803
  # Orphan Package Management
753
804
  Tool(
754
805
  name="list_orphan_packages",
755
- description="[MAINTENANCE] List all orphaned packages (dependencies no longer required by any installed package). Shows package names and total disk space usage. Only works on Arch Linux.",
806
+ description="[MAINTENANCE] List all orphaned packages (dependencies no longer required by any installed package). Shows package names and total disk space usage. Only works on Arch Linux. When to use: After removing packages, find orphaned dependencies that are no longer needed.",
756
807
  inputSchema={
757
808
  "type": "object",
758
809
  "properties": {}
@@ -762,7 +813,7 @@ async def list_tools() -> list[Tool]:
762
813
 
763
814
  Tool(
764
815
  name="remove_orphans",
765
- description="[MAINTENANCE] Remove all orphaned packages to free up disk space. Supports dry-run mode to preview changes and package exclusion. Only works on Arch Linux. Requires sudo access.",
816
+ description="[MAINTENANCE] Remove all orphaned packages to free up disk space. Supports dry-run mode to preview changes and package exclusion. Only works on Arch Linux. Requires sudo access. Example: Use dry_run=true first to preview, then dry_run=false to actually remove. Exclude critical packages with exclude=['pkg1'].",
766
817
  inputSchema={
767
818
  "type": "object",
768
819
  "properties": {
@@ -785,7 +836,7 @@ async def list_tools() -> list[Tool]:
785
836
  # Package Ownership Tools
786
837
  Tool(
787
838
  name="find_package_owner",
788
- description="[ORGANIZATION] Find which package owns a specific file on the system. Useful for troubleshooting and understanding file origins. Only works on Arch Linux.",
839
+ description="[ORGANIZATION] Find which package owns a specific file on the system. Useful for troubleshooting and understanding file origins. Only works on Arch Linux. Example: '/usr/bin/python' → returns 'python' package that owns this file.",
789
840
  inputSchema={
790
841
  "type": "object",
791
842
  "properties": {
@@ -801,7 +852,7 @@ async def list_tools() -> list[Tool]:
801
852
 
802
853
  Tool(
803
854
  name="list_package_files",
804
- description="[ORGANIZATION] List all files owned by a package. Supports optional filtering by pattern. Only works on Arch Linux.",
855
+ description="[ORGANIZATION] List all files owned by a package. Supports optional filtering by pattern. Only works on Arch Linux. Use case: See all files installed by 'systemd' package, optionally filter with pattern='*.service'.",
805
856
  inputSchema={
806
857
  "type": "object",
807
858
  "properties": {
@@ -821,7 +872,7 @@ async def list_tools() -> list[Tool]:
821
872
 
822
873
  Tool(
823
874
  name="search_package_files",
824
- description="[ORGANIZATION] Search for files across all packages in repositories. Requires package database sync (pacman -Fy). Only works on Arch Linux.",
875
+ description="[ORGANIZATION] Search for files across all packages in repositories. Requires package database sync (pacman -Fy). Only works on Arch Linux. Example: Search for '*.desktop' to find all packages that install desktop entries.",
825
876
  inputSchema={
826
877
  "type": "object",
827
878
  "properties": {
@@ -838,7 +889,7 @@ async def list_tools() -> list[Tool]:
838
889
  # Package Verification
839
890
  Tool(
840
891
  name="verify_package_integrity",
841
- description="[MAINTENANCE] Verify the integrity of installed package files. Detects modified, missing, or corrupted files. Only works on Arch Linux.",
892
+ description="[MAINTENANCE] Verify the integrity of installed package files. Detects modified, missing, or corrupted files. Only works on Arch Linux. When to use: After system crash or disk errors, verify 'linux' package files match expected checksums.",
842
893
  inputSchema={
843
894
  "type": "object",
844
895
  "properties": {
@@ -860,7 +911,7 @@ async def list_tools() -> list[Tool]:
860
911
  # Package Groups
861
912
  Tool(
862
913
  name="list_package_groups",
863
- description="[ORGANIZATION] List all available package groups (e.g., base, base-devel, gnome). Only works on Arch Linux.",
914
+ description="[ORGANIZATION] List all available package groups (e.g., base, base-devel, gnome). Only works on Arch Linux. Example: Returns groups like 'base', 'base-devel', 'gnome', 'kde-applications'.",
864
915
  inputSchema={
865
916
  "type": "object",
866
917
  "properties": {}
@@ -870,7 +921,7 @@ async def list_tools() -> list[Tool]:
870
921
 
871
922
  Tool(
872
923
  name="list_group_packages",
873
- description="[ORGANIZATION] List all packages in a specific group. Only works on Arch Linux.",
924
+ description="[ORGANIZATION] List all packages in a specific group. Only works on Arch Linux. Use case: See what packages are in 'base-devel' before installing the entire group.",
874
925
  inputSchema={
875
926
  "type": "object",
876
927
  "properties": {
@@ -887,7 +938,7 @@ async def list_tools() -> list[Tool]:
887
938
  # Install Reason Management
888
939
  Tool(
889
940
  name="list_explicit_packages",
890
- description="[MAINTENANCE] List all packages explicitly installed by the user (not installed as dependencies). Useful for creating backup lists or understanding system composition. Only works on Arch Linux.",
941
+ description="[MAINTENANCE] List all packages explicitly installed by the user (not installed as dependencies). Useful for creating backup lists or understanding system composition. Only works on Arch Linux. When to use: Find packages you explicitly installed (vs dependencies) for system documentation.",
891
942
  inputSchema={
892
943
  "type": "object",
893
944
  "properties": {}
@@ -897,7 +948,7 @@ async def list_tools() -> list[Tool]:
897
948
 
898
949
  Tool(
899
950
  name="mark_as_explicit",
900
- description="[MAINTENANCE] Mark a package as explicitly installed. Prevents it from being removed as an orphan. Only works on Arch Linux.",
951
+ description="[MAINTENANCE] Mark a package as explicitly installed. Prevents it from being removed as an orphan. Only works on Arch Linux. Example: Mark 'python-pip' as explicit if you want to keep it even when dependencies change.",
901
952
  inputSchema={
902
953
  "type": "object",
903
954
  "properties": {
@@ -913,7 +964,7 @@ async def list_tools() -> list[Tool]:
913
964
 
914
965
  Tool(
915
966
  name="mark_as_dependency",
916
- description="[MAINTENANCE] Mark a package as a dependency. Allows it to be removed as an orphan if no packages depend on it. Only works on Arch Linux.",
967
+ description="[MAINTENANCE] Mark a package as a dependency. Allows it to be removed as an orphan if no packages depend on it. Only works on Arch Linux. Use case: Mark 'lib32-gcc-libs' as dependency so it can be auto-removed with orphans later.",
917
968
  inputSchema={
918
969
  "type": "object",
919
970
  "properties": {
@@ -930,7 +981,7 @@ async def list_tools() -> list[Tool]:
930
981
  # System Diagnostic Tools
931
982
  Tool(
932
983
  name="get_system_info",
933
- description="[MONITORING] Get comprehensive system information including kernel version, architecture, hostname, uptime, and memory statistics. Works on any system.",
984
+ description="[MONITORING] Get comprehensive system information including kernel version, architecture, hostname, uptime, and memory statistics. Works on any system. Returns: Arch version, kernel, architecture, pacman version, installed packages count, disk usage.",
934
985
  inputSchema={
935
986
  "type": "object",
936
987
  "properties": {}
@@ -940,7 +991,7 @@ async def list_tools() -> list[Tool]:
940
991
 
941
992
  Tool(
942
993
  name="check_disk_space",
943
- description="[MONITORING] Check disk space usage for critical filesystem paths including root, home, var, and pacman cache. Warns when space is low. Works on any system.",
994
+ description="[MONITORING] Check disk space usage for critical filesystem paths including root, home, var, and pacman cache. Warns when space is low. Works on any system. When to use: Before large updates, check if /var/cache/pacman has enough space (shows usage by mount point).",
944
995
  inputSchema={
945
996
  "type": "object",
946
997
  "properties": {}
@@ -950,7 +1001,7 @@ async def list_tools() -> list[Tool]:
950
1001
 
951
1002
  Tool(
952
1003
  name="get_pacman_cache_stats",
953
- description="[MONITORING] Analyze pacman package cache statistics including size, package count, and cache age. Only works on Arch Linux.",
1004
+ description="[MONITORING] Analyze pacman package cache statistics including size, package count, and cache age. Only works on Arch Linux. Example output: Cache size 2.3GB, 450 packages, oldest package from 2023-01-15.",
954
1005
  inputSchema={
955
1006
  "type": "object",
956
1007
  "properties": {}
@@ -960,7 +1011,7 @@ async def list_tools() -> list[Tool]:
960
1011
 
961
1012
  Tool(
962
1013
  name="check_failed_services",
963
- description="[MONITORING] Check for failed systemd services. Useful for diagnosing system issues. Works on systemd-based systems.",
1014
+ description="[MONITORING] Check for failed systemd services. Useful for diagnosing system issues. Works on systemd-based systems. Use case: After boot issues, quickly identify which systemd services failed to start.",
964
1015
  inputSchema={
965
1016
  "type": "object",
966
1017
  "properties": {}
@@ -970,7 +1021,7 @@ async def list_tools() -> list[Tool]:
970
1021
 
971
1022
  Tool(
972
1023
  name="get_boot_logs",
973
- description="[MONITORING] Retrieve recent boot logs from journalctl. Useful for troubleshooting boot issues. Works on systemd-based systems.",
1024
+ description="[MONITORING] Retrieve recent boot logs from journalctl. Useful for troubleshooting boot issues. Works on systemd-based systems. Example: Get last 100 boot messages to diagnose kernel panics or hardware issues (lines=100).",
974
1025
  inputSchema={
975
1026
  "type": "object",
976
1027
  "properties": {
@@ -988,7 +1039,7 @@ async def list_tools() -> list[Tool]:
988
1039
  # News Tools
989
1040
  Tool(
990
1041
  name="get_latest_news",
991
- description="[DISCOVERY] Fetch recent Arch Linux news from RSS feed. Returns title, date, summary, and link for each news item.",
1042
+ description="[DISCOVERY] Fetch recent Arch Linux news from RSS feed. Returns title, date, summary, and link for each news item. When to use: Before system updates, check archlinux.org news for manual interventions required.",
992
1043
  inputSchema={
993
1044
  "type": "object",
994
1045
  "properties": {
@@ -1009,7 +1060,7 @@ async def list_tools() -> list[Tool]:
1009
1060
 
1010
1061
  Tool(
1011
1062
  name="check_critical_news",
1012
- description="[DISCOVERY] Check for critical Arch Linux news requiring manual intervention. Scans recent news for keywords: 'manual intervention', 'action required', 'breaking change', etc.",
1063
+ description="[DISCOVERY] Check for critical Arch Linux news requiring manual intervention. Scans recent news for keywords: 'manual intervention', 'action required', 'breaking change', etc. Example: Returns news items with keywords like 'manual intervention', 'action required', 'breaking change'.",
1013
1064
  inputSchema={
1014
1065
  "type": "object",
1015
1066
  "properties": {
@@ -1026,7 +1077,7 @@ async def list_tools() -> list[Tool]:
1026
1077
 
1027
1078
  Tool(
1028
1079
  name="get_news_since_last_update",
1029
- description="[DISCOVERY] Get news posted since last pacman update. Parses /var/log/pacman.log for last update timestamp. Only works on Arch Linux.",
1080
+ description="[DISCOVERY] Get news posted since last pacman update. Parses /var/log/pacman.log for last update timestamp. Only works on Arch Linux. Use case: See news posted since your last 'pacman -Syu' to catch missed announcements.",
1030
1081
  inputSchema={
1031
1082
  "type": "object",
1032
1083
  "properties": {}
@@ -1037,7 +1088,7 @@ async def list_tools() -> list[Tool]:
1037
1088
  # Transaction Log Tools
1038
1089
  Tool(
1039
1090
  name="get_transaction_history",
1040
- description="[HISTORY] Get recent package transactions from pacman log. Shows installed, upgraded, and removed packages. Only works on Arch Linux.",
1091
+ description="[HISTORY] Get recent package transactions from pacman log. Shows installed, upgraded, and removed packages. Only works on Arch Linux. Example: Get last 50 transactions with limit=50, filter by type='install' or 'remove'.",
1041
1092
  inputSchema={
1042
1093
  "type": "object",
1043
1094
  "properties": {
@@ -1060,7 +1111,7 @@ async def list_tools() -> list[Tool]:
1060
1111
 
1061
1112
  Tool(
1062
1113
  name="find_when_installed",
1063
- description="[HISTORY] Find when a package was first installed and its upgrade history. Only works on Arch Linux.",
1114
+ description="[HISTORY] Find when a package was first installed and its upgrade history. Only works on Arch Linux. Use case: Check when 'docker' was installed and what version it was.",
1064
1115
  inputSchema={
1065
1116
  "type": "object",
1066
1117
  "properties": {
@@ -1076,7 +1127,7 @@ async def list_tools() -> list[Tool]:
1076
1127
 
1077
1128
  Tool(
1078
1129
  name="find_failed_transactions",
1079
- description="[HISTORY] Find failed package transactions in pacman log. Only works on Arch Linux.",
1130
+ description="[HISTORY] Find failed package transactions in pacman log. Only works on Arch Linux. When to use: After pacman errors, see which transactions failed and why.",
1080
1131
  inputSchema={
1081
1132
  "type": "object",
1082
1133
  "properties": {}
@@ -1086,7 +1137,7 @@ async def list_tools() -> list[Tool]:
1086
1137
 
1087
1138
  Tool(
1088
1139
  name="get_database_sync_history",
1089
- description="[HISTORY] Get database synchronization history. Shows when 'pacman -Sy' was run. Only works on Arch Linux.",
1140
+ description="[HISTORY] Get database synchronization history. Shows when 'pacman -Sy' was run. Only works on Arch Linux. Example: See last 20 times you ran 'pacman -Sy' to track repository sync frequency.",
1090
1141
  inputSchema={
1091
1142
  "type": "object",
1092
1143
  "properties": {
@@ -1104,7 +1155,7 @@ async def list_tools() -> list[Tool]:
1104
1155
  # Mirror Management Tools
1105
1156
  Tool(
1106
1157
  name="list_active_mirrors",
1107
- description="[MIRRORS] List currently configured mirrors from mirrorlist. Only works on Arch Linux.",
1158
+ description="[MIRRORS] List currently configured mirrors from mirrorlist. Only works on Arch Linux. Returns: Current mirrors from /etc/pacman.d/mirrorlist with their URLs and countries.",
1108
1159
  inputSchema={
1109
1160
  "type": "object",
1110
1161
  "properties": {}
@@ -1114,7 +1165,7 @@ async def list_tools() -> list[Tool]:
1114
1165
 
1115
1166
  Tool(
1116
1167
  name="test_mirror_speed",
1117
- description="[MIRRORS] Test mirror response time. Can test a specific mirror or all active mirrors. Only works on Arch Linux.",
1168
+ description="[MIRRORS] Test mirror response time. Can test a specific mirror or all active mirrors. Only works on Arch Linux. Example: Test specific mirror 'https://mirror.example.com' or all active mirrors if no URL provided.",
1118
1169
  inputSchema={
1119
1170
  "type": "object",
1120
1171
  "properties": {
@@ -1130,7 +1181,7 @@ async def list_tools() -> list[Tool]:
1130
1181
 
1131
1182
  Tool(
1132
1183
  name="suggest_fastest_mirrors",
1133
- description="[MIRRORS] Suggest optimal mirrors based on official mirror status from archlinux.org. Filters by country if specified.",
1184
+ description="[MIRRORS] Suggest optimal mirrors based on official mirror status from archlinux.org. Filters by country if specified. Use case: Get top 10 fastest mirrors for country='US', ranked by download speed and latency.",
1134
1185
  inputSchema={
1135
1186
  "type": "object",
1136
1187
  "properties": {
@@ -1151,7 +1202,7 @@ async def list_tools() -> list[Tool]:
1151
1202
 
1152
1203
  Tool(
1153
1204
  name="check_mirrorlist_health",
1154
- description="[MIRRORS] Verify mirror configuration health. Checks for common issues like no active mirrors, outdated mirrorlist, high latency. Only works on Arch Linux.",
1205
+ description="[MIRRORS] Verify mirror configuration health. Checks for common issues like no active mirrors, outdated mirrorlist, high latency. Only works on Arch Linux. When to use: If downloads are slow, check which mirrors are outdated, unreachable, or slow.",
1155
1206
  inputSchema={
1156
1207
  "type": "object",
1157
1208
  "properties": {}
@@ -1162,7 +1213,7 @@ async def list_tools() -> list[Tool]:
1162
1213
  # Configuration Tools
1163
1214
  Tool(
1164
1215
  name="analyze_pacman_conf",
1165
- description="[CONFIG] Parse and analyze pacman.conf. Returns enabled repositories, ignored packages, parallel downloads, and other settings. Only works on Arch Linux.",
1216
+ description="[CONFIG] Parse and analyze pacman.conf. Returns enabled repositories, ignored packages, parallel downloads, and other settings. Only works on Arch Linux. Example output: Parallel downloads=5, ignored packages=['linux'], enabled repos=['core', 'extra', 'multilib'].",
1166
1217
  inputSchema={
1167
1218
  "type": "object",
1168
1219
  "properties": {}
@@ -1172,7 +1223,7 @@ async def list_tools() -> list[Tool]:
1172
1223
 
1173
1224
  Tool(
1174
1225
  name="analyze_makepkg_conf",
1175
- description="[CONFIG] Parse and analyze makepkg.conf. Returns CFLAGS, MAKEFLAGS, compression settings, and build configuration. Only works on Arch Linux.",
1226
+ description="[CONFIG] Parse and analyze makepkg.conf. Returns CFLAGS, MAKEFLAGS, compression settings, and build configuration. Only works on Arch Linux. Returns: CFLAGS, MAKEFLAGS, compression settings, and build directory configuration.",
1176
1227
  inputSchema={
1177
1228
  "type": "object",
1178
1229
  "properties": {}
@@ -1182,7 +1233,7 @@ async def list_tools() -> list[Tool]:
1182
1233
 
1183
1234
  Tool(
1184
1235
  name="check_ignored_packages",
1185
- description="[CONFIG] List packages ignored in updates from pacman.conf. Warns if critical system packages are ignored. Only works on Arch Linux.",
1236
+ description="[CONFIG] List packages ignored in updates from pacman.conf. Warns if critical system packages are ignored. Only works on Arch Linux. Use case: See which packages are in IgnorePkg/IgnoreGroup to understand why they don't update.",
1186
1237
  inputSchema={
1187
1238
  "type": "object",
1188
1239
  "properties": {}
@@ -1192,7 +1243,7 @@ async def list_tools() -> list[Tool]:
1192
1243
 
1193
1244
  Tool(
1194
1245
  name="get_parallel_downloads_setting",
1195
- description="[CONFIG] Get parallel downloads configuration from pacman.conf and provide recommendations. Only works on Arch Linux.",
1246
+ description="[CONFIG] Get parallel downloads configuration from pacman.conf and provide recommendations. Only works on Arch Linux. Example: Returns current ParallelDownloads value (default=5) from pacman.conf.",
1196
1247
  inputSchema={
1197
1248
  "type": "object",
1198
1249
  "properties": {}
@@ -1202,7 +1253,7 @@ async def list_tools() -> list[Tool]:
1202
1253
 
1203
1254
  Tool(
1204
1255
  name="check_database_freshness",
1205
- description="[MAINTENANCE] Check when package databases were last synchronized. Warns if databases are stale (> 24 hours). Only works on Arch Linux.",
1256
+ description="[MAINTENANCE] Check when package databases were last synchronized. Warns if databases are stale (> 24 hours). Only works on Arch Linux. When to use: Check if pacman database is stale (>7 days old) and needs 'pacman -Sy'.",
1206
1257
  inputSchema={
1207
1258
  "type": "object",
1208
1259
  "properties": {}
@@ -1212,7 +1263,7 @@ async def list_tools() -> list[Tool]:
1212
1263
 
1213
1264
  Tool(
1214
1265
  name="run_system_health_check",
1215
- description="[MONITORING] Run a comprehensive system health check. Integrates multiple diagnostics to provide a complete overview of system status, including disk space, failed services, updates, orphan packages, and more. Only works on Arch Linux.",
1266
+ description="[MONITORING] Run a comprehensive system health check. Integrates multiple diagnostics to provide a complete overview of system status, including disk space, failed services, updates, orphan packages, and more. Only works on Arch Linux. Comprehensive check: Updates available, disk space, failed services, database freshness, orphans, and critical news.",
1216
1267
  inputSchema={
1217
1268
  "type": "object",
1218
1269
  "properties": {}
@@ -1259,14 +1310,14 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1259
1310
 
1260
1311
  elif name == "check_updates_dry_run":
1261
1312
  if not IS_ARCH:
1262
- return [TextContent(type="text", text="Error: check_updates_dry_run only available on Arch Linux systems")]
1313
+ return [TextContent(type="text", text=create_platform_error_message("check_updates_dry_run"))]
1263
1314
 
1264
1315
  result = await check_updates_dry_run()
1265
1316
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1266
1317
 
1267
1318
  elif name == "install_package_secure":
1268
1319
  if not IS_ARCH:
1269
- return [TextContent(type="text", text="Error: install_package_secure only available on Arch Linux systems")]
1320
+ return [TextContent(type="text", text=create_platform_error_message("install_package_secure"))]
1270
1321
 
1271
1322
  package_name = arguments["package_name"]
1272
1323
  result = await install_package_secure(package_name)
@@ -1285,7 +1336,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1285
1336
  # Package Removal Tools
1286
1337
  elif name == "remove_package":
1287
1338
  if not IS_ARCH:
1288
- return [TextContent(type="text", text="Error: remove_package only available on Arch Linux systems")]
1339
+ return [TextContent(type="text", text=create_platform_error_message("remove_package"))]
1289
1340
 
1290
1341
  package_name = arguments["package_name"]
1291
1342
  remove_dependencies = arguments.get("remove_dependencies", False)
@@ -1295,7 +1346,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1295
1346
 
1296
1347
  elif name == "remove_packages_batch":
1297
1348
  if not IS_ARCH:
1298
- return [TextContent(type="text", text="Error: remove_packages_batch only available on Arch Linux systems")]
1349
+ return [TextContent(type="text", text=create_platform_error_message("remove_packages_batch"))]
1299
1350
 
1300
1351
  package_names = arguments["package_names"]
1301
1352
  remove_dependencies = arguments.get("remove_dependencies", False)
@@ -1305,14 +1356,14 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1305
1356
  # Orphan Package Management
1306
1357
  elif name == "list_orphan_packages":
1307
1358
  if not IS_ARCH:
1308
- return [TextContent(type="text", text="Error: list_orphan_packages only available on Arch Linux systems")]
1359
+ return [TextContent(type="text", text=create_platform_error_message("list_orphan_packages"))]
1309
1360
 
1310
1361
  result = await list_orphan_packages()
1311
1362
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1312
1363
 
1313
1364
  elif name == "remove_orphans":
1314
1365
  if not IS_ARCH:
1315
- return [TextContent(type="text", text="Error: remove_orphans only available on Arch Linux systems")]
1366
+ return [TextContent(type="text", text=create_platform_error_message("remove_orphans"))]
1316
1367
 
1317
1368
  dry_run = arguments.get("dry_run", True)
1318
1369
  exclude = arguments.get("exclude", None)
@@ -1322,7 +1373,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1322
1373
  # Package Ownership Tools
1323
1374
  elif name == "find_package_owner":
1324
1375
  if not IS_ARCH:
1325
- return [TextContent(type="text", text="Error: find_package_owner only available on Arch Linux systems")]
1376
+ return [TextContent(type="text", text=create_platform_error_message("find_package_owner"))]
1326
1377
 
1327
1378
  file_path = arguments["file_path"]
1328
1379
  result = await find_package_owner(file_path)
@@ -1330,7 +1381,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1330
1381
 
1331
1382
  elif name == "list_package_files":
1332
1383
  if not IS_ARCH:
1333
- return [TextContent(type="text", text="Error: list_package_files only available on Arch Linux systems")]
1384
+ return [TextContent(type="text", text=create_platform_error_message("list_package_files"))]
1334
1385
 
1335
1386
  package_name = arguments["package_name"]
1336
1387
  filter_pattern = arguments.get("filter_pattern", None)
@@ -1339,7 +1390,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1339
1390
 
1340
1391
  elif name == "search_package_files":
1341
1392
  if not IS_ARCH:
1342
- return [TextContent(type="text", text="Error: search_package_files only available on Arch Linux systems")]
1393
+ return [TextContent(type="text", text=create_platform_error_message("search_package_files"))]
1343
1394
 
1344
1395
  filename_pattern = arguments["filename_pattern"]
1345
1396
  result = await search_package_files(filename_pattern)
@@ -1348,7 +1399,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1348
1399
  # Package Verification
1349
1400
  elif name == "verify_package_integrity":
1350
1401
  if not IS_ARCH:
1351
- return [TextContent(type="text", text="Error: verify_package_integrity only available on Arch Linux systems")]
1402
+ return [TextContent(type="text", text=create_platform_error_message("verify_package_integrity"))]
1352
1403
 
1353
1404
  package_name = arguments["package_name"]
1354
1405
  thorough = arguments.get("thorough", False)
@@ -1358,14 +1409,14 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1358
1409
  # Package Groups
1359
1410
  elif name == "list_package_groups":
1360
1411
  if not IS_ARCH:
1361
- return [TextContent(type="text", text="Error: list_package_groups only available on Arch Linux systems")]
1412
+ return [TextContent(type="text", text=create_platform_error_message("list_package_groups"))]
1362
1413
 
1363
1414
  result = await list_package_groups()
1364
1415
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1365
1416
 
1366
1417
  elif name == "list_group_packages":
1367
1418
  if not IS_ARCH:
1368
- return [TextContent(type="text", text="Error: list_group_packages only available on Arch Linux systems")]
1419
+ return [TextContent(type="text", text=create_platform_error_message("list_group_packages"))]
1369
1420
 
1370
1421
  group_name = arguments["group_name"]
1371
1422
  result = await list_group_packages(group_name)
@@ -1374,14 +1425,14 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1374
1425
  # Install Reason Management
1375
1426
  elif name == "list_explicit_packages":
1376
1427
  if not IS_ARCH:
1377
- return [TextContent(type="text", text="Error: list_explicit_packages only available on Arch Linux systems")]
1428
+ return [TextContent(type="text", text=create_platform_error_message("list_explicit_packages"))]
1378
1429
 
1379
1430
  result = await list_explicit_packages()
1380
1431
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1381
1432
 
1382
1433
  elif name == "mark_as_explicit":
1383
1434
  if not IS_ARCH:
1384
- return [TextContent(type="text", text="Error: mark_as_explicit only available on Arch Linux systems")]
1435
+ return [TextContent(type="text", text=create_platform_error_message("mark_as_explicit"))]
1385
1436
 
1386
1437
  package_name = arguments["package_name"]
1387
1438
  result = await mark_as_explicit(package_name)
@@ -1389,7 +1440,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1389
1440
 
1390
1441
  elif name == "mark_as_dependency":
1391
1442
  if not IS_ARCH:
1392
- return [TextContent(type="text", text="Error: mark_as_dependency only available on Arch Linux systems")]
1443
+ return [TextContent(type="text", text=create_platform_error_message("mark_as_dependency"))]
1393
1444
 
1394
1445
  package_name = arguments["package_name"]
1395
1446
  result = await mark_as_dependency(package_name)
@@ -1406,7 +1457,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1406
1457
 
1407
1458
  elif name == "get_pacman_cache_stats":
1408
1459
  if not IS_ARCH:
1409
- return [TextContent(type="text", text="Error: get_pacman_cache_stats only available on Arch Linux systems")]
1460
+ return [TextContent(type="text", text=create_platform_error_message("get_pacman_cache_stats"))]
1410
1461
 
1411
1462
  result = await get_pacman_cache_stats()
1412
1463
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
@@ -1434,7 +1485,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1434
1485
 
1435
1486
  elif name == "get_news_since_last_update":
1436
1487
  if not IS_ARCH:
1437
- return [TextContent(type="text", text="Error: get_news_since_last_update only available on Arch Linux systems")]
1488
+ return [TextContent(type="text", text=create_platform_error_message("get_news_since_last_update"))]
1438
1489
 
1439
1490
  result = await get_news_since_last_update()
1440
1491
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
@@ -1442,7 +1493,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1442
1493
  # Transaction log tools
1443
1494
  elif name == "get_transaction_history":
1444
1495
  if not IS_ARCH:
1445
- return [TextContent(type="text", text="Error: get_transaction_history only available on Arch Linux systems")]
1496
+ return [TextContent(type="text", text=create_platform_error_message("get_transaction_history"))]
1446
1497
 
1447
1498
  limit = arguments.get("limit", 50)
1448
1499
  transaction_type = arguments.get("transaction_type", "all")
@@ -1451,7 +1502,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1451
1502
 
1452
1503
  elif name == "find_when_installed":
1453
1504
  if not IS_ARCH:
1454
- return [TextContent(type="text", text="Error: find_when_installed only available on Arch Linux systems")]
1505
+ return [TextContent(type="text", text=create_platform_error_message("find_when_installed"))]
1455
1506
 
1456
1507
  package_name = arguments.get("package_name")
1457
1508
  if not package_name:
@@ -1462,14 +1513,14 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1462
1513
 
1463
1514
  elif name == "find_failed_transactions":
1464
1515
  if not IS_ARCH:
1465
- return [TextContent(type="text", text="Error: find_failed_transactions only available on Arch Linux systems")]
1516
+ return [TextContent(type="text", text=create_platform_error_message("find_failed_transactions"))]
1466
1517
 
1467
1518
  result = await find_failed_transactions()
1468
1519
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1469
1520
 
1470
1521
  elif name == "get_database_sync_history":
1471
1522
  if not IS_ARCH:
1472
- return [TextContent(type="text", text="Error: get_database_sync_history only available on Arch Linux systems")]
1523
+ return [TextContent(type="text", text=create_platform_error_message("get_database_sync_history"))]
1473
1524
 
1474
1525
  limit = arguments.get("limit", 20)
1475
1526
  result = await get_database_sync_history(limit=limit)
@@ -1478,14 +1529,14 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1478
1529
  # Mirror management tools
1479
1530
  elif name == "list_active_mirrors":
1480
1531
  if not IS_ARCH:
1481
- return [TextContent(type="text", text="Error: list_active_mirrors only available on Arch Linux systems")]
1532
+ return [TextContent(type="text", text=create_platform_error_message("list_active_mirrors"))]
1482
1533
 
1483
1534
  result = await list_active_mirrors()
1484
1535
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1485
1536
 
1486
1537
  elif name == "test_mirror_speed":
1487
1538
  if not IS_ARCH:
1488
- return [TextContent(type="text", text="Error: test_mirror_speed only available on Arch Linux systems")]
1539
+ return [TextContent(type="text", text=create_platform_error_message("test_mirror_speed"))]
1489
1540
 
1490
1541
  mirror_url = arguments.get("mirror_url")
1491
1542
  result = await test_mirror_speed(mirror_url=mirror_url)
@@ -1499,7 +1550,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1499
1550
 
1500
1551
  elif name == "check_mirrorlist_health":
1501
1552
  if not IS_ARCH:
1502
- return [TextContent(type="text", text="Error: check_mirrorlist_health only available on Arch Linux systems")]
1553
+ return [TextContent(type="text", text=create_platform_error_message("check_mirrorlist_health"))]
1503
1554
 
1504
1555
  result = await check_mirrorlist_health()
1505
1556
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
@@ -1507,42 +1558,42 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent |
1507
1558
  # Configuration tools
1508
1559
  elif name == "analyze_pacman_conf":
1509
1560
  if not IS_ARCH:
1510
- return [TextContent(type="text", text="Error: analyze_pacman_conf only available on Arch Linux systems")]
1561
+ return [TextContent(type="text", text=create_platform_error_message("analyze_pacman_conf"))]
1511
1562
 
1512
1563
  result = await analyze_pacman_conf()
1513
1564
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1514
1565
 
1515
1566
  elif name == "analyze_makepkg_conf":
1516
1567
  if not IS_ARCH:
1517
- return [TextContent(type="text", text="Error: analyze_makepkg_conf only available on Arch Linux systems")]
1568
+ return [TextContent(type="text", text=create_platform_error_message("analyze_makepkg_conf"))]
1518
1569
 
1519
1570
  result = await analyze_makepkg_conf()
1520
1571
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1521
1572
 
1522
1573
  elif name == "check_ignored_packages":
1523
1574
  if not IS_ARCH:
1524
- return [TextContent(type="text", text="Error: check_ignored_packages only available on Arch Linux systems")]
1575
+ return [TextContent(type="text", text=create_platform_error_message("check_ignored_packages"))]
1525
1576
 
1526
1577
  result = await check_ignored_packages()
1527
1578
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1528
1579
 
1529
1580
  elif name == "get_parallel_downloads_setting":
1530
1581
  if not IS_ARCH:
1531
- return [TextContent(type="text", text="Error: get_parallel_downloads_setting only available on Arch Linux systems")]
1582
+ return [TextContent(type="text", text=create_platform_error_message("get_parallel_downloads_setting"))]
1532
1583
 
1533
1584
  result = await get_parallel_downloads_setting()
1534
1585
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1535
1586
 
1536
1587
  elif name == "run_system_health_check":
1537
1588
  if not IS_ARCH:
1538
- return [TextContent(type="text", text="Error: run_system_health_check only available on Arch Linux systems")]
1589
+ return [TextContent(type="text", text=create_platform_error_message("run_system_health_check"))]
1539
1590
 
1540
1591
  result = await run_system_health_check()
1541
1592
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
1542
1593
 
1543
1594
  elif name == "check_database_freshness":
1544
1595
  if not IS_ARCH:
1545
- return [TextContent(type="text", text="Error: check_database_freshness only available on Arch Linux systems")]
1596
+ return [TextContent(type="text", text=create_platform_error_message("check_database_freshness"))]
1546
1597
 
1547
1598
  result = await check_database_freshness()
1548
1599
  return [TextContent(type="text", text=json.dumps(result, indent=2))]
@@ -1883,7 +1934,7 @@ paru -S {package_name} # or yay -S {package_name}
1883
1934
  role="assistant",
1884
1935
  content=PromptMessage.TextContent(
1885
1936
  type="text",
1886
- text="Error: safe_system_update prompt only available on Arch Linux systems"
1937
+ text=create_platform_error_message("safe_system_update prompt")
1887
1938
  )
1888
1939
  )
1889
1940
  ]
@@ -2038,7 +2089,7 @@ paru -S {package_name} # or yay -S {package_name}
2038
2089
  role="assistant",
2039
2090
  content=PromptMessage.TextContent(
2040
2091
  type="text",
2041
- text="Error: cleanup_system prompt only available on Arch Linux systems"
2092
+ text=create_platform_error_message("cleanup_system prompt")
2042
2093
  )
2043
2094
  )
2044
2095
  ]
@@ -2214,7 +2265,7 @@ Be detailed and provide specific mirror URLs and configuration commands."""
2214
2265
  role="assistant",
2215
2266
  content=PromptMessage.TextContent(
2216
2267
  type="text",
2217
- text="Error: system_health_check prompt only available on Arch Linux systems"
2268
+ text=create_platform_error_message("system_health_check prompt")
2218
2269
  )
2219
2270
  )
2220
2271
  ]