Skip to content

feat: implement APT backend for Debian/Debian-derivative support#20

Merged
ereslibre merged 1 commit intomainfrom
ereslibre/implement-apt-backend
Feb 3, 2026
Merged

feat: implement APT backend for Debian/Debian-derivative support#20
ereslibre merged 1 commit intomainfrom
ereslibre/implement-apt-backend

Conversation

@ereslibre
Copy link
Copy Markdown
Contributor

@ereslibre ereslibre commented Feb 2, 2026

Introduce APT backend support for Debian/Debian-derivative systems alongside the existing APK backend for Alpine Linux. The codebase is refactored from a single APK-specific implementation into a trait-based architecture with a generic PackageManagerHandler<T> that works with any backend implementing the PackageManager trait. The server auto-detects the host OS at runtime via file system markers (/etc/alpine-release, /etc/debian_version) and selects the appropriate backend.

Changes

  • Added PackageManager trait defining a common interface (install_package, install_package_with_version, search_package, list_installed_packages, refresh_repositories)
  • Introduced PackageManagerHandler<T: PackageManager> generic handler that implements ServerHandler once for all backends
  • Moved APK-specific logic from src/apk.rs into src/backend/apk.rs as an Apk struct implementing PackageManager
  • Added src/backend/apt.rs with Apt struct implementing PackageManager using apt-get, apt-cache, and apt commands with DEBIAN_FRONTEND=noninteractive
  • Added OS auto-detection in main.rs to select the correct backend at startup
  • Updated tool descriptions and error messages to be backend-aware (dynamically reference the active package manager name and OS)
  • Updated AGENTS.md, Makefile, and .dev-mcp.json to reflect multi-backend support

Notes

The APT backend uses apt-cache madison for version lookup in install_package_with_version, compared to APK's multi-repository search approach. Input validation for APT additionally allows colons (for architecture-qualified package names like package:amd64) and tildes (for Debian version strings like 1.0~beta).

flowchart TD
    Start([Server starts]) --> Detect{OS detection}
    Detect -->|/etc/alpine-release| APK[PackageManagerHandler&lt;Apk&gt;]
    Detect -->|/etc/debian_version| APT[PackageManagerHandler&lt;Apt&gt;]
    Detect -->|Neither| Err[Exit with error]
    APK --> MCP[MCP endpoint at /mcp]
    APT --> MCP
Loading

Closes: #7

@ereslibre ereslibre self-assigned this Feb 2, 2026
@ereslibre ereslibre marked this pull request as ready for review February 3, 2026 09:02
@ereslibre ereslibre changed the title feat: implement APT backend feat: implement APT backend for Debian/Ubuntu support Feb 3, 2026
@ereslibre ereslibre changed the title feat: implement APT backend for Debian/Ubuntu support feat: implement APT backend for Debian/Debian-derivative support Feb 3, 2026
@ereslibre ereslibre force-pushed the ereslibre/implement-apt-backend branch from accdb20 to cfeb98d Compare February 3, 2026 09:13
Copy link
Copy Markdown
Contributor

@Angelmmiguel Angelmmiguel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!! 👏

Comment thread src/backend/mod.rs
@@ -194,19 +314,19 @@ impl ServerHandler for Apk {
Ok(exec_result) => {
if exec_result.status == 0 {
let success_message =
format!("✓ Package '{package}' was installed successfully.");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving some tokens hehe

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was the initial proposal and I said well.. why not :)

Comment thread src/main.rs
Comment on lines +38 to +58
let router = if std::path::Path::new("/etc/alpine-release").exists() {
tracing::info!("Detected Alpine Linux, using APK backend");
let handler = PackageManagerHandler::new(Apk::new());
let service = StreamableHttpService::new(
move || Ok(handler.clone()),
LocalSessionManager::default().into(),
Default::default(),
);
axum::Router::new().nest_service("/mcp", service)
} else if std::path::Path::new("/etc/debian_version").exists() {
tracing::info!("Detected Debian/Debian-derivative, using APT backend");
let handler = PackageManagerHandler::new(Apt::new());
let service = StreamableHttpService::new(
move || Ok(handler.clone()),
LocalSessionManager::default().into(),
Default::default(),
);
axum::Router::new().nest_service("/mcp", service)
} else {
anyhow::bail!("Unsupported OS: neither Alpine nor Debian detected");
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this!

@ereslibre ereslibre merged commit ceed50b into main Feb 3, 2026
3 checks passed
@ereslibre ereslibre deleted the ereslibre/implement-apt-backend branch February 3, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement apt backend

2 participants