portainer-mcp/bin/portainer-core-mcp
Adolfo Delorenzo be1e05c382 Simplify authentication to require URL and API key only
Major configuration and tooling updates:

Authentication Changes:
- Remove username/password authentication support
- Require PORTAINER_URL and PORTAINER_API_KEY (both mandatory)
- Simplify PortainerConfig class and validation logic
- Update all documentation to reflect API key requirement

Multiple Runtime Support:
- Add uvx support for running without installation
- Add uv support with dedicated wrapper script
- Add npx support with Node.js wrapper script
- Maintain backward compatibility with direct Python execution

Documentation Updates:
- Comprehensive README.md with all execution methods
- Detailed USAGE.md with step-by-step instructions
- Updated .env.example with clear required vs optional sections
- Enhanced docstrings in server.py and config.py

Tooling Support:
- package.json for npm/npx support with cross-platform wrapper
- scripts/run-with-uv.py for uv integration
- bin/portainer-core-mcp Node.js wrapper for npx
- test_uvx.py for uvx functionality testing

Configuration Improvements:
- Clear separation of required vs optional environment variables
- Better validation error messages
- Simplified authentication flow
- Enhanced project metadata in pyproject.toml

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 07:48:23 -06:00

115 lines
3.0 KiB
JavaScript
Executable File

#!/usr/bin/env node
const { spawn } = require('child_process');
const path = require('path');
// Get the directory where this script is located
const scriptDir = path.dirname(__filename);
const runServerPath = path.join(scriptDir, '..', 'run_server.py');
// Check if Python is available
function checkPython() {
return new Promise((resolve, reject) => {
const pythonCmd = process.platform === 'win32' ? 'python' : 'python3';
const proc = spawn(pythonCmd, ['--version'], { stdio: 'pipe' });
proc.on('close', (code) => {
if (code === 0) {
resolve(pythonCmd);
} else {
// Try alternative python command
const altPythonCmd = 'python';
const altProc = spawn(altPythonCmd, ['--version'], { stdio: 'pipe' });
altProc.on('close', (altCode) => {
if (altCode === 0) {
resolve(altPythonCmd);
} else {
reject(new Error('Python is not installed or not in PATH'));
}
});
}
});
});
}
// Run the Python server
async function runServer() {
try {
const pythonCmd = await checkPython();
console.log('🚀 Starting Portainer Core MCP Server via npx...');
const proc = spawn(pythonCmd, [runServerPath], {
stdio: 'inherit',
cwd: path.dirname(runServerPath)
});
proc.on('error', (err) => {
console.error('❌ Failed to start server:', err.message);
process.exit(1);
});
proc.on('close', (code) => {
if (code !== 0) {
console.error(`❌ Server exited with code ${code}`);
process.exit(code);
}
});
// Handle signals
process.on('SIGINT', () => {
console.log('\n👋 Stopping server...');
proc.kill('SIGINT');
});
process.on('SIGTERM', () => {
console.log('\n👋 Stopping server...');
proc.kill('SIGTERM');
});
} catch (error) {
console.error('❌ Error:', error.message);
console.error('💡 Please ensure Python 3.8+ is installed and in your PATH');
process.exit(1);
}
}
// Show help
function showHelp() {
console.log(`
Portainer Core MCP Server
Usage:
npx portainer-core-mcp [options]
Options:
-h, --help Show this help message
-v, --version Show version information
Environment Variables:
PORTAINER_URL Portainer instance URL (required)
PORTAINER_API_KEY Portainer API key (required)
LOG_LEVEL Logging level (default: INFO)
DEBUG Enable debug mode (default: false)
Examples:
npx portainer-core-mcp
PORTAINER_URL=https://portainer.example.com PORTAINER_API_KEY=your-key npx portainer-core-mcp
`);
}
// Main
const args = process.argv.slice(2);
if (args.includes('-h') || args.includes('--help')) {
showHelp();
process.exit(0);
}
if (args.includes('-v') || args.includes('--version')) {
const packageJson = require('../package.json');
console.log(`portainer-core-mcp v${packageJson.version}`);
process.exit(0);
}
runServer().catch(console.error);