Skip to content

Fix lxc node assignment#2

Open
davidgregoriom wants to merge 2 commits intogilby125:mainfrom
davidgregoriom:fix-lxc-node-assignment
Open

Fix lxc node assignment#2
davidgregoriom wants to merge 2 commits intogilby125:mainfrom
davidgregoriom:fix-lxc-node-assignment

Conversation

@davidgregoriom
Copy link

@davidgregoriom davidgregoriom commented Oct 11, 2025

Summary by CodeRabbit

  • New Features
    • Introduced a Proxmox MCP server with tools for clusters, nodes, VMs, and storage.
    • Added ProxmoxManager for authenticated API requests.
  • Bug Fixes
    • Corrected node field mapping when aggregating LXC VMs.
  • Tests
    • Added unit tests for cluster, node, storage, and VM tools.
  • Chores
    • Added TypeScript build setup and configuration.
    • Added Jest configuration and test scripts.
    • Updated start script to run compiled output.
    • Adjusted .gitignore to ignore node_modules.

This commit fixes a bug in the `getVMs` function where the node for LXC containers was not being correctly assigned. The code was previously using `vm.node || node.node`, but `vm.node` is not a valid property for LXC containers returned from the Proxmox API. This resulted in the node being incorrectly assigned.

The fix changes the code to use `node.node` directly, which correctly assigns the node from the parent loop.

Additionally, this commit introduces a new test file to verify the fix and prevent regressions. The test mocks the Proxmox API and asserts that the node is correctly assigned to the LXC container.
This commit migrates the entire project from JavaScript to TypeScript. This includes:

- Setting up a TypeScript environment with a `tsconfig.json` file.
- Creating a `src` directory with the new TypeScript source code.
- Migrating all the core components and tools to TypeScript.
- Adding type definitions for the Proxmox API responses.
- Writing new tests for the migrated code using Jest and `ts-jest`.
- Updating the `package.json` file with the necessary dependencies and scripts for building and testing the application.

The new TypeScript codebase is more maintainable and less prone to errors due to the static type checking provided by TypeScript.
@coderabbitai
Copy link

coderabbitai bot commented Oct 11, 2025

Walkthrough

Introduces a TypeScript-based Proxmox MCP server with tool modules (nodes, VMs, storage, cluster), a Proxmox API manager, Jest tests, and TypeScript configs. Adjusts package scripts and dependencies, adds Jest config, and TypeScript compiler settings. Updates ignore rules and exports a class in index.js.

Changes

Cohort / File(s) Summary
Build & Tooling
package.json, tsconfig.json, jest.config.cjs, .gitignore
Adds TypeScript build (tsc), dev, and test scripts; switches start to dist/server.js. Introduces tsconfig. Adds Jest config with ts-jest and moduleNameMapper. Replaces Python ignores with node_modules. Downgrades node-fetch to v2 and adds dev typings.
Core Proxmox Client
src/core/proxmox.ts, src/types/index.ts
Adds ProxmoxManager for authenticated Proxmox API requests with SSL handling and JSON parsing. Adds ProxmoxConfig and AuthConfig interfaces.
MCP Server
src/server.ts
Adds ProxmoxMCPServer wiring MCP tools, handling ListTools and CallTool requests, and starting via stdio transport. Includes env-based config bootstrap.
Tools: Cluster
src/tools/cluster.ts
Adds cluster tools registry with get_cluster_status invoking /cluster/status.
Tools: Node
src/tools/node.ts
Adds node tools registry: get_nodes (lists /nodes) and get_node_status (/nodes/{node}/status).
Tools: Storage
src/tools/storage.ts
Adds storage tool get_storage; fetches per-node storage and aggregates, optionally filtered by node.
Tools: VM
src/tools/vm.ts
Adds VM tools: get_vms (across nodes/types), get_vm_status, and execute_vm_command via agent exec.
Tests
tests/*.test.ts
Adds Jest tests for cluster, node, storage, and VM tools, mocking proxmoxRequest and asserting outputs/endpoints.
Legacy JS export tweak
index.js
Exports ProxmoxServer; adjusts LXC node field mapping in getVMs aggregation.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Server as MCP Server
  participant Tools as Tool Registries<br/>(Node/VM/Storage/Cluster)
  participant PM as ProxmoxManager
  note over Server,Tools: New: MCP routing across tool registries

  Client->>Server: ListTools
  Server->>Tools: Aggregate listTools()
  Tools-->>Server: Tool definitions
  Server-->>Client: Combined tool list

  Client->>Server: CallTool(name, args)
  alt Tool found in Node/VM/Storage/Cluster
    Server->>Tools: getTool(name)
    Tools-->>Server: toolFn
    Server->>toolFn: invoke(args)
    toolFn->>PM: proxmoxRequest(endpoint, method?, body?)
    PM-->>toolFn: data
    toolFn-->>Server: content[text JSON]
    Server-->>Client: Result
  else Unknown tool
    Server-->>Client: Error content
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

In burrowed wires I thump with glee,
New tools sprout up like clover tea.
Nodes and VMs, storage in tow,
Cluster whispers status low.
TypeScript trails where packets hop—
I nibble tests until they pop.
Happy hops on stdio! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title “Fix lxc node assignment” only highlights a minor change in index.js, but the pull request actually introduces a large TypeScript migration, adds a ProxmoxManager class, an MCP server, various tooling modules, configuration updates, and a suite of tests, so it does not accurately summarize the primary scope of the changeset. Please revise the title to encompass the broader set of changes, for example “Migrate to TypeScript, add ProxmoxManager and tooling modules, configure Jest/tsconfig, and fix LXC node assignment” so the main objectives are clear at a glance.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (6)
.gitignore (1)

1-1: Consider adding common Node.js/TypeScript ignore patterns.

The current .gitignore only excludes node_modules, but TypeScript projects typically benefit from ignoring additional artifacts and sensitive files.

Apply this diff to add recommended patterns:

 node_modules
+dist/
+*.log
+.env
+.DS_Store
+*.swp
+.vscode/
+.idea/

Note: If you intend to commit dist/ for deployment purposes, keep the current configuration and ignore this suggestion.

src/core/proxmox.ts (1)

34-38: Consider using a more specific type for fetch options.

Line 34 uses any type for the options object. For better type safety, consider using node-fetch's RequestInit type.

Apply this diff:

+import fetch, { RequestInit } from 'node-fetch';
 import https from 'https';
 import { ProxmoxConfig, AuthConfig } from '../types/index.js';
-        const options: any = {
+        const options: RequestInit = {
             method,
             headers,
             agent: this.httpsAgent
tests/node.test.ts (1)

1-42: LGTM!

The test suite follows good patterns with proper setup, mocking, and assertions. The tests cover the main success paths for node tooling.

Consider adding tests for error scenarios:

  • What happens when proxmoxRequest fails?
  • What happens when invalid node names are provided?

These would improve resilience verification but are not essential given the current implementation's simplicity.

tests/storage.test.ts (1)

1-37: LGTM!

The test correctly verifies storage aggregation across nodes. The mock sequence and assertions align with the implementation in src/tools/storage.ts.

Consider adding a test for the single-node filter path:

const result = await getStorage({ node: 'pve1' });

This would ensure both code paths are covered.

src/server.ts (1)

43-67: LGTM!

The sequential tool lookup pattern is straightforward and appropriate for the current number of tool providers.

For better performance with many tool providers, consider using a Map for O(1) lookup:

private setupToolHandlers(): void {
    const nodeTools = getNodeTools(this.proxmoxManager);
    const vmTools = getVmTools(this.proxmoxManager);
    const storageTools = getStorageTools(this.proxmoxManager);
    const clusterTools = getClusterTools(this.proxmoxManager);
    
    const toolProviders = [nodeTools, vmTools, storageTools, clusterTools];
    
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
        const { name, arguments: args } = request.params;
        
        try {
            for (const provider of toolProviders) {
                const tool = provider.getTool(name);
                if (tool) {
                    return await tool(args as any);
                }
            }
            throw new Error(`Unknown tool: ${name}`);
        } catch (error: any) {
            return {
                content: [{
                    type: 'text',
                    text: `Error: ${error.message}`
                }]
            };
        }
    });
}

This eliminates code duplication and makes adding new providers easier.

src/tools/vm.ts (1)

92-108: LGTM!

The getVmStatus and executeVmCommand functions correctly construct API endpoints using the type parameter and handle both qemu and lxc VM types.

Consider adding stronger typing for the args parameters:

interface VmStatusArgs {
    node: string;
    vmid: string;
    type?: 'qemu' | 'lxc';
}

interface ExecuteVmCommandArgs {
    node: string;
    vmid: string;
    command: string;
    type?: 'qemu' | 'lxc';
}

const getVmStatus = async (args: VmStatusArgs) => { /* ... */ };
const executeVmCommand = async (args: ExecuteVmCommandArgs) => { /* ... */ };

This provides better IDE support and catches type errors at compile time, but it's not essential for the current implementation.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a9ad90 and 3d10352.

⛔ Files ignored due to path filters (8)
  • dist/core/proxmox.js is excluded by !**/dist/**
  • dist/server.js is excluded by !**/dist/**
  • dist/tools/cluster.js is excluded by !**/dist/**
  • dist/tools/node.js is excluded by !**/dist/**
  • dist/tools/storage.js is excluded by !**/dist/**
  • dist/tools/vm.js is excluded by !**/dist/**
  • dist/types/index.js is excluded by !**/dist/**
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • .gitignore (1 hunks)
  • index.js (2 hunks)
  • jest.config.cjs (1 hunks)
  • package.json (1 hunks)
  • src/core/proxmox.ts (1 hunks)
  • src/server.ts (1 hunks)
  • src/tools/cluster.ts (1 hunks)
  • src/tools/node.ts (1 hunks)
  • src/tools/storage.ts (1 hunks)
  • src/tools/vm.ts (1 hunks)
  • src/types/index.ts (1 hunks)
  • tests/cluster.test.ts (1 hunks)
  • tests/node.test.ts (1 hunks)
  • tests/storage.test.ts (1 hunks)
  • tests/vm.test.ts (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
tests/storage.test.ts (3)
src/core/proxmox.ts (2)
  • ProxmoxManager (5-66)
  • proxmoxRequest (25-65)
src/types/index.ts (2)
  • ProxmoxConfig (1-5)
  • AuthConfig (7-11)
src/tools/storage.ts (1)
  • getStorageTools (3-51)
tests/cluster.test.ts (3)
src/core/proxmox.ts (2)
  • ProxmoxManager (5-66)
  • proxmoxRequest (25-65)
src/types/index.ts (2)
  • ProxmoxConfig (1-5)
  • AuthConfig (7-11)
src/tools/cluster.ts (1)
  • getClusterTools (3-37)
src/core/proxmox.ts (2)
dist/server.js (1)
  • config (74-81)
src/types/index.ts (2)
  • ProxmoxConfig (1-5)
  • AuthConfig (7-11)
src/tools/cluster.ts (1)
src/core/proxmox.ts (1)
  • ProxmoxManager (5-66)
tests/node.test.ts (3)
src/core/proxmox.ts (2)
  • ProxmoxManager (5-66)
  • proxmoxRequest (25-65)
src/types/index.ts (2)
  • ProxmoxConfig (1-5)
  • AuthConfig (7-11)
src/tools/node.ts (1)
  • getNodeTools (3-57)
src/tools/vm.ts (1)
src/core/proxmox.ts (1)
  • ProxmoxManager (5-66)
src/tools/node.ts (1)
src/core/proxmox.ts (1)
  • ProxmoxManager (5-66)
src/tools/storage.ts (1)
src/core/proxmox.ts (1)
  • ProxmoxManager (5-66)
src/server.ts (6)
src/core/proxmox.ts (1)
  • ProxmoxManager (5-66)
src/types/index.ts (2)
  • ProxmoxConfig (1-5)
  • AuthConfig (7-11)
src/tools/node.ts (1)
  • getNodeTools (3-57)
src/tools/vm.ts (1)
  • getVmTools (3-114)
src/tools/storage.ts (1)
  • getStorageTools (3-51)
src/tools/cluster.ts (1)
  • getClusterTools (3-37)
tests/vm.test.ts (3)
src/core/proxmox.ts (2)
  • ProxmoxManager (5-66)
  • proxmoxRequest (25-65)
src/types/index.ts (2)
  • ProxmoxConfig (1-5)
  • AuthConfig (7-11)
src/tools/vm.ts (1)
  • getVmTools (3-114)
🔇 Additional comments (8)
index.js (1)

276-334: LGTM! The LXC node assignment fix is correct.

Line 300 now consistently uses node.node for LXC VMs, matching the QEMU pattern at line 295. This ensures that when aggregating VMs without a node filter, both QEMU and LXC VMs report the node they were actually fetched from, eliminating potential inconsistencies.

package.json (1)

16-16: Verify the node-fetch version downgrade is intentional.

The package was downgraded from ^3.3.2 to ^2.7.0. Since the project uses "type": "module" (ESM), and node-fetch v3 is ESM-native, this downgrade may be unnecessary unless there's a specific compatibility requirement.

Based on learnings

Please confirm:

  • Is there a specific reason for using v2 instead of v3?
  • Are there compatibility concerns with dependencies or tooling?

If no specific reason exists, consider upgrading back to v3 for better ESM support:

-    "node-fetch": "^2.7.0"
+    "node-fetch": "^3.3.2"
src/tools/cluster.ts (1)

1-37: LGTM!

The cluster tooling implementation follows the established factory pattern consistently. The code is clean and straightforward.

jest.config.cjs (1)

1-13: LGTM!

The Jest configuration is appropriate for a TypeScript project:

  • Uses ts-jest preset for TypeScript compilation
  • moduleNameMapper correctly handles .js extension mapping (TypeScript outputs .js in imports while source files are .ts)
  • transformIgnorePatterns allows node-fetch to be transformed (necessary for ESM/CommonJS interop)

Based on learnings: ts-jest 29.4.5 aligns well with Jest 29 and modern TypeScript.

tests/vm.test.ts (1)

1-57: LGTM!

The test suite comprehensively covers VM tooling operations:

  • VM listing with proper node and type annotation
  • VM status retrieval
  • Command execution via agent

The mock sequence correctly simulates the multi-node, multi-type VM aggregation logic.

src/server.ts (1)

88-96: Verify environment variable handling.

The server reads configuration from environment variables with sensible defaults. However, ensure that PROXMOX_TOKEN_VALUE is never logged or exposed in error messages, as it's a sensitive credential.

Consider adding validation to fail fast if required credentials are missing:

const config: ProxmoxConfig & AuthConfig = {
    host: process.env.PROXMOX_HOST || 'localhost',
    port: parseInt(process.env.PROXMOX_PORT || '8006', 10),
    verify_ssl: process.env.PROXMOX_VERIFY_SSL === 'true',
    user: process.env.PROXMOX_USER || 'root@pam',
    token_name: process.env.PROXMOX_TOKEN_NAME || 'mcp-server',
    token_value: process.env.PROXMOX_TOKEN_VALUE || '',
};

if (!config.token_value) {
    throw new Error('PROXMOX_TOKEN_VALUE environment variable is required');
}

This prevents silent failures when credentials are misconfigured.

src/tools/node.ts (1)

1-57: LGTM!

The node tooling implementation is clean and follows the established factory pattern. The tool definitions include clear descriptions and proper input schemas.

src/tools/vm.ts (1)

60-90: LGTM! The LXC node assignment is now correct.

The getVms function properly assigns the node field to both qemu and lxc VMs in both single-node and multi-node paths:

  • Single-node path (lines 64-72): Uses args.node for both VM types ✓
  • Multi-node path (lines 73-85): Uses node.node from the loop variable for both VM types ✓

This fix (indicated by the PR title) ensures LXC containers receive the correct node assignment when querying across all nodes.

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.

1 participant