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>
This commit is contained in:
115
bin/portainer-core-mcp
Executable file
115
bin/portainer-core-mcp
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/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);
|
Reference in New Issue
Block a user