- Complete MCP server for Incus container management - 10 tools for instance lifecycle operations (create, start, stop, etc.) - 2 resources for instance and remote server data - Support for multiple Incus remotes with TLS authentication - TypeScript implementation with comprehensive error handling - Test suite for validation and integration testing - MCP configuration for Claude Code integration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
169 lines
4.1 KiB
JavaScript
169 lines
4.1 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
import { spawn } from 'child_process';
|
|
|
|
class TestClient {
|
|
private client: Client;
|
|
private transport: StdioClientTransport;
|
|
|
|
constructor() {
|
|
// Spawn the MCP server process
|
|
const serverProcess = spawn('node', ['../build/index.js'], {
|
|
stdio: ['pipe', 'pipe', 'inherit'],
|
|
cwd: __dirname,
|
|
});
|
|
|
|
this.transport = new StdioClientTransport({
|
|
reader: serverProcess.stdout!,
|
|
writer: serverProcess.stdin!,
|
|
});
|
|
|
|
this.client = new Client(
|
|
{
|
|
name: 'incus-mcp-test-client',
|
|
version: '0.1.0',
|
|
},
|
|
{
|
|
capabilities: {},
|
|
}
|
|
);
|
|
}
|
|
|
|
async connect() {
|
|
await this.client.connect(this.transport);
|
|
console.log('✅ Connected to Incus MCP server');
|
|
}
|
|
|
|
async testListTools() {
|
|
console.log('\n🔧 Testing list tools...');
|
|
try {
|
|
const result = await this.client.request(
|
|
{ method: 'tools/list' },
|
|
{ method: 'tools/list' }
|
|
);
|
|
console.log(`Found ${result.tools.length} tools:`);
|
|
result.tools.forEach((tool: any) => {
|
|
console.log(` - ${tool.name}: ${tool.description}`);
|
|
});
|
|
} catch (error) {
|
|
console.error('❌ Error listing tools:', error);
|
|
}
|
|
}
|
|
|
|
async testListResources() {
|
|
console.log('\n📚 Testing list resources...');
|
|
try {
|
|
const result = await this.client.request(
|
|
{ method: 'resources/list' },
|
|
{ method: 'resources/list' }
|
|
);
|
|
console.log(`Found ${result.resources.length} resources:`);
|
|
result.resources.forEach((resource: any) => {
|
|
console.log(` - ${resource.uri}: ${resource.name}`);
|
|
});
|
|
} catch (error) {
|
|
console.error('❌ Error listing resources:', error);
|
|
}
|
|
}
|
|
|
|
async testIncusInfo() {
|
|
console.log('\n💻 Testing incus info...');
|
|
try {
|
|
const result = await this.client.request(
|
|
{
|
|
method: 'tools/call',
|
|
params: {
|
|
name: 'incus_info',
|
|
arguments: {},
|
|
},
|
|
},
|
|
{
|
|
method: 'tools/call',
|
|
params: {
|
|
name: 'incus_info',
|
|
arguments: {},
|
|
},
|
|
}
|
|
);
|
|
console.log('Incus info result:', result);
|
|
} catch (error) {
|
|
console.error('❌ Error getting incus info:', error);
|
|
}
|
|
}
|
|
|
|
async testListInstances() {
|
|
console.log('\n📦 Testing list instances...');
|
|
try {
|
|
const result = await this.client.request(
|
|
{
|
|
method: 'tools/call',
|
|
params: {
|
|
name: 'incus_list_instances',
|
|
arguments: {},
|
|
},
|
|
},
|
|
{
|
|
method: 'tools/call',
|
|
params: {
|
|
name: 'incus_list_instances',
|
|
arguments: {},
|
|
},
|
|
}
|
|
);
|
|
console.log('Instances list result:', result);
|
|
} catch (error) {
|
|
console.error('❌ Error listing instances:', error);
|
|
}
|
|
}
|
|
|
|
async testListRemotes() {
|
|
console.log('\n🌐 Testing list remotes...');
|
|
try {
|
|
const result = await this.client.request(
|
|
{
|
|
method: 'tools/call',
|
|
params: {
|
|
name: 'incus_list_remotes',
|
|
arguments: {},
|
|
},
|
|
},
|
|
{
|
|
method: 'tools/call',
|
|
params: {
|
|
name: 'incus_list_remotes',
|
|
arguments: {},
|
|
},
|
|
}
|
|
);
|
|
console.log('Remotes list result:', result);
|
|
} catch (error) {
|
|
console.error('❌ Error listing remotes:', error);
|
|
}
|
|
}
|
|
|
|
async runTests() {
|
|
try {
|
|
await this.connect();
|
|
await this.testListTools();
|
|
await this.testListResources();
|
|
await this.testIncusInfo();
|
|
await this.testListInstances();
|
|
await this.testListRemotes();
|
|
console.log('\n✅ All tests completed');
|
|
} catch (error) {
|
|
console.error('❌ Test failed:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run tests
|
|
async function main() {
|
|
const testClient = new TestClient();
|
|
await testClient.runTests();
|
|
}
|
|
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
main().catch(console.error);
|
|
} |