193
src/__tests__/index.test.ts
Archivo normal
193
src/__tests__/index.test.ts
Archivo normal
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* Test suite for CUDA Quantum MCP Server
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
|
||||
import CudaQuantumMCPServer from '../index.js';
|
||||
import { LogLevel } from '../utils/logger.js';
|
||||
|
||||
describe('CUDA Quantum MCP Server', () => {
|
||||
let server: CudaQuantumMCPServer;
|
||||
|
||||
beforeAll(async () => {
|
||||
server = new CudaQuantumMCPServer({
|
||||
name: 'test-server',
|
||||
version: '1.0.0',
|
||||
logLevel: LogLevel.ERROR, // Reduce noise during testing
|
||||
defaultTarget: 'qpp-cpu'
|
||||
});
|
||||
|
||||
// Note: In a real test, you'd mock the Python bridge
|
||||
// For now, we'll just test the server instantiation
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (server) {
|
||||
await server.shutdown();
|
||||
}
|
||||
});
|
||||
|
||||
describe('Server Initialization', () => {
|
||||
it('should create server instance', () => {
|
||||
expect(server).toBeDefined();
|
||||
expect(server.getServer()).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have correct server info', () => {
|
||||
const serverInstance = server.getServer();
|
||||
expect(serverInstance).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tool Validation', () => {
|
||||
const validKernelInput = {
|
||||
name: 'test_kernel',
|
||||
num_qubits: 2
|
||||
};
|
||||
|
||||
const validGateInput = {
|
||||
kernel_name: 'test_kernel',
|
||||
gate_name: 'h',
|
||||
qubits: [0]
|
||||
};
|
||||
|
||||
it('should validate create_quantum_kernel input', () => {
|
||||
expect(validKernelInput.name).toBe('test_kernel');
|
||||
expect(validKernelInput.num_qubits).toBe(2);
|
||||
});
|
||||
|
||||
it('should validate apply_quantum_gate input', () => {
|
||||
expect(validGateInput.kernel_name).toBe('test_kernel');
|
||||
expect(validGateInput.gate_name).toBe('h');
|
||||
expect(validGateInput.qubits).toEqual([0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Input Validation', () => {
|
||||
it('should reject invalid qubit counts', () => {
|
||||
const invalidInput = {
|
||||
name: 'test',
|
||||
num_qubits: 0 // Should be >= 1
|
||||
};
|
||||
|
||||
expect(invalidInput.num_qubits).toBeLessThan(1);
|
||||
});
|
||||
|
||||
it('should reject empty kernel names', () => {
|
||||
const invalidInput = {
|
||||
name: '', // Should not be empty
|
||||
num_qubits: 2
|
||||
};
|
||||
|
||||
expect(invalidInput.name).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Quantum Circuit Tools', () => {
|
||||
describe('Gate Validation', () => {
|
||||
const supportedGates = ['h', 'x', 'y', 'z', 's', 't', 'rx', 'ry', 'rz', 'cx', 'cy', 'cz', 'ccx', 'swap', 'cswap'];
|
||||
|
||||
it('should support all standard gates', () => {
|
||||
supportedGates.forEach(gate => {
|
||||
expect(supportedGates).toContain(gate);
|
||||
});
|
||||
});
|
||||
|
||||
it('should validate parameterized gates', () => {
|
||||
const parameterizedGates = ['rx', 'ry', 'rz'];
|
||||
|
||||
parameterizedGates.forEach(gate => {
|
||||
expect(supportedGates).toContain(gate);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Hardware Backend Types', () => {
|
||||
const simulators = ['qpp-cpu', 'qpp-gpu', 'density-matrix-cpu', 'tensor-network'];
|
||||
const hardware = ['ionq', 'quantinuum', 'quantum_machines', 'infleqtion', 'iqm', 'oqc', 'pasqal'];
|
||||
|
||||
it('should define simulator backends', () => {
|
||||
expect(simulators.length).toBeGreaterThan(0);
|
||||
expect(simulators).toContain('qpp-cpu');
|
||||
expect(simulators).toContain('qpp-gpu');
|
||||
});
|
||||
|
||||
it('should define hardware backends', () => {
|
||||
expect(hardware.length).toBeGreaterThan(0);
|
||||
expect(hardware).toContain('ionq');
|
||||
expect(hardware).toContain('quantinuum');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Configuration Validation', () => {
|
||||
it('should validate environment variables', () => {
|
||||
const envVars = [
|
||||
'CUDAQ_PYTHON_PATH',
|
||||
'CUDAQ_DEFAULT_TARGET',
|
||||
'CUDA_VISIBLE_DEVICES',
|
||||
'LOG_LEVEL'
|
||||
];
|
||||
|
||||
envVars.forEach(envVar => {
|
||||
expect(typeof envVar).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have valid default configuration', () => {
|
||||
const config = {
|
||||
name: 'cuda-quantum-mcp',
|
||||
version: '1.0.0',
|
||||
defaultTarget: 'qpp-cpu',
|
||||
logLevel: LogLevel.INFO
|
||||
};
|
||||
|
||||
expect(config.name).toBe('cuda-quantum-mcp');
|
||||
expect(config.version).toBe('1.0.0');
|
||||
expect(config.defaultTarget).toBe('qpp-cpu');
|
||||
expect(config.logLevel).toBe(LogLevel.INFO);
|
||||
});
|
||||
});
|
||||
|
||||
// Mock tests for Python bridge functionality
|
||||
describe('Python Bridge (Mocked)', () => {
|
||||
it('should handle CUDA Quantum not available', async () => {
|
||||
// Mock scenario where CUDA Quantum is not installed
|
||||
const mockResponse = {
|
||||
success: false,
|
||||
error: 'CUDA Quantum not available'
|
||||
};
|
||||
|
||||
expect(mockResponse.success).toBe(false);
|
||||
expect(mockResponse.error).toContain('CUDA Quantum');
|
||||
});
|
||||
|
||||
it('should handle successful kernel creation', async () => {
|
||||
// Mock successful kernel creation
|
||||
const mockResponse = {
|
||||
success: true,
|
||||
kernel_name: 'test_kernel'
|
||||
};
|
||||
|
||||
expect(mockResponse.success).toBe(true);
|
||||
expect(mockResponse.kernel_name).toBe('test_kernel');
|
||||
});
|
||||
|
||||
it('should handle sampling results', async () => {
|
||||
// Mock sampling results
|
||||
const mockResponse = {
|
||||
success: true,
|
||||
result: {
|
||||
counts: {'00': 500, '11': 500},
|
||||
shots: 1000
|
||||
}
|
||||
};
|
||||
|
||||
expect(mockResponse.success).toBe(true);
|
||||
expect(mockResponse.result.shots).toBe(1000);
|
||||
expect(Object.keys(mockResponse.result.counts)).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
export {};
|
||||
354
src/bridge/python-bridge.ts
Archivo normal
354
src/bridge/python-bridge.ts
Archivo normal
@@ -0,0 +1,354 @@
|
||||
/**
|
||||
* CUDA Quantum Python Bridge for Node.js
|
||||
* Provides seamless integration with CUDA Quantum Python API
|
||||
*/
|
||||
|
||||
import { spawn, ChildProcess } from 'child_process';
|
||||
import path from 'path';
|
||||
import { EventEmitter } from 'events';
|
||||
import {
|
||||
PythonCall,
|
||||
PythonResponse,
|
||||
ExecutionResult,
|
||||
QuantumKernel,
|
||||
Hamiltonian,
|
||||
MeasurementCounts,
|
||||
StateVector
|
||||
} from '../types/index.js';
|
||||
import { Logger } from '../utils/logger.js';
|
||||
|
||||
export interface PythonBridgeConfig {
|
||||
pythonPath?: string;
|
||||
scriptPath?: string;
|
||||
timeout?: number;
|
||||
maxMemory?: number;
|
||||
}
|
||||
|
||||
export class PythonBridge extends EventEmitter {
|
||||
private pythonProcess: ChildProcess | null = null;
|
||||
private config: Required<PythonBridgeConfig>;
|
||||
private logger: Logger;
|
||||
private requestQueue: Map<string, {
|
||||
resolve: (value: PythonResponse) => void;
|
||||
reject: (reason: any) => void;
|
||||
timeout: NodeJS.Timeout;
|
||||
}> = new Map();
|
||||
private requestId = 0;
|
||||
|
||||
constructor(config: PythonBridgeConfig = {}) {
|
||||
super();
|
||||
|
||||
this.config = {
|
||||
pythonPath: config.pythonPath || process.env.CUDAQ_PYTHON_PATH || 'python3',
|
||||
scriptPath: config.scriptPath || path.join(__dirname, '../../python/cudaq_bridge.py'),
|
||||
timeout: config.timeout || 60000,
|
||||
maxMemory: config.maxMemory || 2048
|
||||
};
|
||||
|
||||
this.logger = new Logger('PythonBridge');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Python bridge
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
try {
|
||||
await this.startPythonProcess();
|
||||
this.logger.info('Python bridge initialized successfully');
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to initialize Python bridge:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the Python process
|
||||
*/
|
||||
private async startPythonProcess(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.pythonProcess = spawn(this.config.pythonPath, [this.config.scriptPath], {
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
env: {
|
||||
...process.env,
|
||||
PYTHONUNBUFFERED: '1',
|
||||
CUDA_VISIBLE_DEVICES: process.env.CUDA_VISIBLE_DEVICES || '0'
|
||||
}
|
||||
});
|
||||
|
||||
let initialized = false;
|
||||
|
||||
this.pythonProcess.stdout?.on('data', (data: Buffer) => {
|
||||
const output = data.toString();
|
||||
this.logger.debug('Python stdout:', output);
|
||||
|
||||
if (!initialized && output.includes('CUDA Quantum Python Bridge')) {
|
||||
initialized = true;
|
||||
resolve();
|
||||
}
|
||||
|
||||
// Handle JSON responses
|
||||
this.handlePythonResponse(output);
|
||||
});
|
||||
|
||||
this.pythonProcess.stderr?.on('data', (data: Buffer) => {
|
||||
const error = data.toString();
|
||||
this.logger.error('Python stderr:', error);
|
||||
|
||||
if (!initialized) {
|
||||
reject(new Error(`Python process error: ${error}`));
|
||||
}
|
||||
});
|
||||
|
||||
this.pythonProcess.on('error', (error) => {
|
||||
this.logger.error('Python process error:', error);
|
||||
if (!initialized) {
|
||||
reject(error);
|
||||
}
|
||||
this.emit('error', error);
|
||||
});
|
||||
|
||||
this.pythonProcess.on('exit', (code) => {
|
||||
this.logger.info(`Python process exited with code ${code}`);
|
||||
this.pythonProcess = null;
|
||||
this.emit('exit', code);
|
||||
});
|
||||
|
||||
// Timeout for initialization
|
||||
setTimeout(() => {
|
||||
if (!initialized) {
|
||||
reject(new Error('Python process initialization timeout'));
|
||||
}
|
||||
}, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle responses from Python process
|
||||
*/
|
||||
private handlePythonResponse(output: string): void {
|
||||
try {
|
||||
const lines = output.split('\n').filter(line => line.trim());
|
||||
|
||||
for (const line of lines) {
|
||||
try {
|
||||
const response = JSON.parse(line);
|
||||
|
||||
if (response.request_id) {
|
||||
const pending = this.requestQueue.get(response.request_id);
|
||||
if (pending) {
|
||||
clearTimeout(pending.timeout);
|
||||
this.requestQueue.delete(response.request_id);
|
||||
pending.resolve(response);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore non-JSON lines
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('Error handling Python response:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send command to Python process
|
||||
*/
|
||||
private async sendCommand(command: string, args: Record<string, any> = {}): Promise<PythonResponse> {
|
||||
if (!this.pythonProcess || !this.pythonProcess.stdin) {
|
||||
throw new Error('Python process not running');
|
||||
}
|
||||
|
||||
const requestId = (++this.requestId).toString();
|
||||
const commandData = { command, request_id: requestId, ...args };
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
this.requestQueue.delete(requestId);
|
||||
reject(new Error(`Python command timeout: ${command}`));
|
||||
}, this.config.timeout);
|
||||
|
||||
this.requestQueue.set(requestId, { resolve, reject, timeout });
|
||||
|
||||
const commandJson = JSON.stringify(commandData) + '\n';
|
||||
this.pythonProcess!.stdin!.write(commandJson);
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Quantum Kernel Operations
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Create a new quantum kernel
|
||||
*/
|
||||
async createKernel(name: string, numQubits: number, parameters?: any[]): Promise<PythonResponse> {
|
||||
return this.sendCommand('create_kernel', {
|
||||
name,
|
||||
num_qubits: numQubits,
|
||||
parameters: parameters || []
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a quantum gate to a kernel
|
||||
*/
|
||||
async applyGate(
|
||||
kernelName: string,
|
||||
gateName: string,
|
||||
qubits: number[],
|
||||
parameters?: number[],
|
||||
controls?: number[],
|
||||
adjoint?: boolean
|
||||
): Promise<PythonResponse> {
|
||||
return this.sendCommand('apply_gate', {
|
||||
kernel_name: kernelName,
|
||||
gate_name: gateName,
|
||||
qubits,
|
||||
parameters,
|
||||
controls,
|
||||
adjoint
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* List available kernels
|
||||
*/
|
||||
async listKernels(): Promise<PythonResponse> {
|
||||
return this.sendCommand('list_kernels');
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Quantum Execution Operations
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Set quantum execution target
|
||||
*/
|
||||
async setTarget(target: string, configuration?: Record<string, any>): Promise<PythonResponse> {
|
||||
return this.sendCommand('set_target', {
|
||||
target,
|
||||
configuration
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample measurement results
|
||||
*/
|
||||
async sample(
|
||||
kernelName: string,
|
||||
shots: number = 1000,
|
||||
parameters?: Record<string, any>
|
||||
): Promise<PythonResponse> {
|
||||
return this.sendCommand('sample', {
|
||||
kernel_name: kernelName,
|
||||
shots,
|
||||
parameters
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute expectation value
|
||||
*/
|
||||
async observe(
|
||||
kernelName: string,
|
||||
hamiltonianTerms: any[],
|
||||
shots: number = 1000,
|
||||
parameters?: Record<string, any>
|
||||
): Promise<PythonResponse> {
|
||||
return this.sendCommand('observe', {
|
||||
kernel_name: kernelName,
|
||||
hamiltonian_terms: hamiltonianTerms,
|
||||
shots,
|
||||
parameters
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get quantum state vector
|
||||
*/
|
||||
async getState(
|
||||
kernelName: string,
|
||||
parameters?: Record<string, any>
|
||||
): Promise<PythonResponse> {
|
||||
return this.sendCommand('get_state', {
|
||||
kernel_name: kernelName,
|
||||
parameters
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform information
|
||||
*/
|
||||
async getPlatformInfo(): Promise<PythonResponse> {
|
||||
return this.sendCommand('get_platform_info');
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Utility Methods
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Check if CUDA Quantum is available
|
||||
*/
|
||||
async checkCudaQuantum(): Promise<boolean> {
|
||||
try {
|
||||
const response = await this.sendCommand('get_platform_info');
|
||||
return response.success === true;
|
||||
} catch (error) {
|
||||
this.logger.error('Error checking CUDA Quantum availability:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup and close the Python process
|
||||
*/
|
||||
async close(): Promise<void> {
|
||||
if (this.pythonProcess) {
|
||||
this.pythonProcess.kill();
|
||||
this.pythonProcess = null;
|
||||
}
|
||||
|
||||
// Clear pending requests
|
||||
for (const [id, request] of this.requestQueue) {
|
||||
clearTimeout(request.timeout);
|
||||
request.reject(new Error('Python bridge closed'));
|
||||
}
|
||||
this.requestQueue.clear();
|
||||
|
||||
this.logger.info('Python bridge closed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the bridge is ready
|
||||
*/
|
||||
isReady(): boolean {
|
||||
return this.pythonProcess !== null && !this.pythonProcess.killed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton instance of Python bridge
|
||||
*/
|
||||
let bridgeInstance: PythonBridge | null = null;
|
||||
|
||||
/**
|
||||
* Get or create Python bridge instance
|
||||
*/
|
||||
export function getPythonBridge(config?: PythonBridgeConfig): PythonBridge {
|
||||
if (!bridgeInstance) {
|
||||
bridgeInstance = new PythonBridge(config);
|
||||
}
|
||||
return bridgeInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Python bridge
|
||||
*/
|
||||
export async function initializePythonBridge(config?: PythonBridgeConfig): Promise<PythonBridge> {
|
||||
const bridge = getPythonBridge(config);
|
||||
await bridge.initialize();
|
||||
return bridge;
|
||||
}
|
||||
|
||||
export default PythonBridge;
|
||||
315
src/index.ts
Archivo normal
315
src/index.ts
Archivo normal
@@ -0,0 +1,315 @@
|
||||
/**
|
||||
* Main MCP Server for CUDA Quantum
|
||||
* Provides comprehensive quantum computing capabilities through the Model Context Protocol
|
||||
*/
|
||||
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
} from '@modelcontextprotocol/sdk/types.js';
|
||||
import { z } from 'zod';
|
||||
import { initializePythonBridge, getPythonBridge } from './bridge/python-bridge.js';
|
||||
import { Logger, LogLevel } from './utils/logger.js';
|
||||
|
||||
// Import tool modules
|
||||
import {
|
||||
quantumCircuitTools,
|
||||
handleCreateQuantumKernel,
|
||||
handleApplyQuantumGate,
|
||||
handleAddMeasurement,
|
||||
handleCreateCommonCircuit,
|
||||
handleListQuantumKernels,
|
||||
handleVisualizeCircuit
|
||||
} from './tools/circuit-tools.js';
|
||||
|
||||
import {
|
||||
quantumExecutionTools,
|
||||
handleSampleQuantumCircuit,
|
||||
handleObserveHamiltonian,
|
||||
handleGetQuantumState,
|
||||
handleRunQuantumAlgorithm,
|
||||
handleVariationalOptimization
|
||||
} from './tools/execution-tools.js';
|
||||
|
||||
import {
|
||||
hardwareBackendTools,
|
||||
handleSetQuantumTarget,
|
||||
handleListQuantumBackends,
|
||||
handleGetPlatformInfo,
|
||||
handleTestBackendConnectivity,
|
||||
handleConfigureGpuAcceleration
|
||||
} from './tools/hardware-tools.js';
|
||||
|
||||
/**
|
||||
* MCP Server configuration interface
|
||||
*/
|
||||
interface ServerConfig {
|
||||
name: string;
|
||||
version: string;
|
||||
pythonPath?: string;
|
||||
defaultTarget?: string;
|
||||
logLevel?: LogLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* CUDA Quantum MCP Server class
|
||||
*/
|
||||
export class CudaQuantumMCPServer {
|
||||
private server: Server;
|
||||
private logger: Logger;
|
||||
private config: ServerConfig;
|
||||
|
||||
constructor(config: ServerConfig) {
|
||||
this.config = {
|
||||
name: 'cuda-quantum-mcp',
|
||||
version: '1.0.0',
|
||||
...config
|
||||
};
|
||||
|
||||
this.logger = new Logger('MCPServer', {
|
||||
level: config.logLevel || LogLevel.INFO
|
||||
});
|
||||
|
||||
this.server = new Server(
|
||||
{
|
||||
name: this.config.name,
|
||||
version: this.config.version,
|
||||
description: 'CUDA Quantum MCP Server - Quantum computing with NVIDIA GPU acceleration'
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
this.setupToolHandlers();
|
||||
this.setupErrorHandling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up tool request handlers
|
||||
*/
|
||||
private setupToolHandlers(): void {
|
||||
// List available tools
|
||||
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
const allTools = [
|
||||
...quantumCircuitTools,
|
||||
...quantumExecutionTools,
|
||||
...hardwareBackendTools
|
||||
];
|
||||
|
||||
return {
|
||||
tools: allTools
|
||||
};
|
||||
});
|
||||
|
||||
// Handle tool execution requests
|
||||
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
this.logger.info(`Executing tool: ${name}`);
|
||||
this.logger.debug(`Tool arguments:`, args);
|
||||
|
||||
try {
|
||||
switch (name) {
|
||||
// Quantum Circuit Tools
|
||||
case 'create_quantum_kernel':
|
||||
return await handleCreateQuantumKernel(args);
|
||||
case 'apply_quantum_gate':
|
||||
return await handleApplyQuantumGate(args);
|
||||
case 'add_measurement':
|
||||
return await handleAddMeasurement(args);
|
||||
case 'create_common_circuit':
|
||||
return await handleCreateCommonCircuit(args);
|
||||
case 'list_quantum_kernels':
|
||||
return await handleListQuantumKernels(args);
|
||||
case 'visualize_circuit':
|
||||
return await handleVisualizeCircuit(args);
|
||||
|
||||
// Quantum Execution Tools
|
||||
case 'sample_quantum_circuit':
|
||||
return await handleSampleQuantumCircuit(args);
|
||||
case 'observe_hamiltonian':
|
||||
return await handleObserveHamiltonian(args);
|
||||
case 'get_quantum_state':
|
||||
return await handleGetQuantumState(args);
|
||||
case 'run_quantum_algorithm':
|
||||
return await handleRunQuantumAlgorithm(args);
|
||||
case 'variational_optimization':
|
||||
return await handleVariationalOptimization(args);
|
||||
|
||||
// Hardware Backend Tools
|
||||
case 'set_quantum_target':
|
||||
return await handleSetQuantumTarget(args);
|
||||
case 'list_quantum_backends':
|
||||
return await handleListQuantumBackends(args);
|
||||
case 'get_platform_info':
|
||||
return await handleGetPlatformInfo(args);
|
||||
case 'test_backend_connectivity':
|
||||
return await handleTestBackendConnectivity(args);
|
||||
case 'configure_gpu_acceleration':
|
||||
return await handleConfigureGpuAcceleration(args);
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(`Error executing tool ${name}:`, error);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error executing ${name}: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up error handling
|
||||
*/
|
||||
private setupErrorHandling(): void {
|
||||
this.server.onerror = (error) => {
|
||||
this.logger.error('MCP Server error:', error);
|
||||
};
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
this.logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (error) => {
|
||||
this.logger.error('Uncaught Exception:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// Graceful shutdown
|
||||
process.on('SIGINT', () => {
|
||||
this.logger.info('Received SIGINT, shutting down gracefully...');
|
||||
this.shutdown();
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
this.logger.info('Received SIGTERM, shutting down gracefully...');
|
||||
this.shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the MCP server
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
try {
|
||||
this.logger.info('Initializing CUDA Quantum MCP Server...');
|
||||
|
||||
// Initialize Python bridge
|
||||
await initializePythonBridge({
|
||||
pythonPath: this.config.pythonPath,
|
||||
timeout: 60000
|
||||
});
|
||||
|
||||
// Set default target if specified
|
||||
if (this.config.defaultTarget) {
|
||||
const bridge = getPythonBridge();
|
||||
await bridge.setTarget(this.config.defaultTarget);
|
||||
this.logger.info(`Set default quantum target: ${this.config.defaultTarget}`);
|
||||
}
|
||||
|
||||
this.logger.info('CUDA Quantum MCP Server initialized successfully');
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to initialize MCP server:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the MCP server
|
||||
*/
|
||||
async start(): Promise<void> {
|
||||
try {
|
||||
await this.initialize();
|
||||
|
||||
const transport = new StdioServerTransport();
|
||||
await this.server.connect(transport);
|
||||
|
||||
this.logger.info(`CUDA Quantum MCP Server started (${this.config.name} v${this.config.version})`);
|
||||
this.logger.info('Available tools: quantum circuits, execution, hardware backends');
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to start MCP server:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the server gracefully
|
||||
*/
|
||||
async shutdown(): Promise<void> {
|
||||
try {
|
||||
this.logger.info('Shutting down CUDA Quantum MCP Server...');
|
||||
|
||||
// Close Python bridge
|
||||
const bridge = getPythonBridge();
|
||||
if (bridge.isReady()) {
|
||||
await bridge.close();
|
||||
}
|
||||
|
||||
await this.server.close();
|
||||
|
||||
this.logger.info('MCP Server shutdown complete');
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
this.logger.error('Error during server shutdown:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server instance for testing
|
||||
*/
|
||||
getServer(): Server {
|
||||
return this.server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point for the MCP server
|
||||
*/
|
||||
async function main(): Promise<void> {
|
||||
// Load configuration from environment variables
|
||||
const config: ServerConfig = {
|
||||
name: process.env.MCP_SERVER_NAME || 'cuda-quantum-mcp',
|
||||
version: process.env.MCP_SERVER_VERSION || '1.0.0',
|
||||
pythonPath: process.env.CUDAQ_PYTHON_PATH,
|
||||
defaultTarget: process.env.CUDAQ_DEFAULT_TARGET || 'qpp-cpu',
|
||||
logLevel: process.env.LOG_LEVEL === 'debug' ? LogLevel.DEBUG :
|
||||
process.env.LOG_LEVEL === 'warn' ? LogLevel.WARN :
|
||||
process.env.LOG_LEVEL === 'error' ? LogLevel.ERROR :
|
||||
LogLevel.INFO
|
||||
};
|
||||
|
||||
const server = new CudaQuantumMCPServer(config);
|
||||
|
||||
try {
|
||||
await server.start();
|
||||
} catch (error) {
|
||||
console.error('Failed to start CUDA Quantum MCP Server:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the server if this file is run directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
export default CudaQuantumMCPServer;
|
||||
503
src/tools/circuit-tools.ts
Archivo normal
503
src/tools/circuit-tools.ts
Archivo normal
@@ -0,0 +1,503 @@
|
||||
/**
|
||||
* Quantum Circuit Building Tools for MCP Server
|
||||
* Provides tools for creating and manipulating quantum circuits
|
||||
*/
|
||||
|
||||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||||
import {
|
||||
CreateKernelSchema,
|
||||
ApplyGateSchema,
|
||||
CreateKernelInput,
|
||||
ApplyGateInput
|
||||
} from '../types/index.js';
|
||||
import { getPythonBridge } from '../bridge/python-bridge.js';
|
||||
import { Logger } from '../utils/logger.js';
|
||||
|
||||
const logger = new Logger('QuantumCircuitTools');
|
||||
|
||||
/**
|
||||
* Tool for creating a new quantum kernel/circuit
|
||||
*/
|
||||
export const createQuantumKernelTool: Tool = {
|
||||
name: 'create_quantum_kernel',
|
||||
description: 'Create a new quantum kernel (circuit) with specified number of qubits and optional parameters',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
num_qubits: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 32,
|
||||
description: 'Number of qubits in the quantum register'
|
||||
},
|
||||
parameters: {
|
||||
type: 'array',
|
||||
description: 'Optional parameters for the kernel',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
type: {
|
||||
type: 'string',
|
||||
enum: ['int', 'float', 'complex', 'list[int]', 'list[float]', 'list[complex]']
|
||||
},
|
||||
default: { description: 'Default value for the parameter' }
|
||||
},
|
||||
required: ['name', 'type']
|
||||
}
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: 'Optional description of the kernel'
|
||||
}
|
||||
},
|
||||
required: ['name', 'num_qubits']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for applying quantum gates to a kernel
|
||||
*/
|
||||
export const applyQuantumGateTool: Tool = {
|
||||
name: 'apply_quantum_gate',
|
||||
description: 'Apply a quantum gate to specified qubits in a quantum kernel',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to modify'
|
||||
},
|
||||
gate_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum gate to apply',
|
||||
enum: ['h', 'x', 'y', 'z', 's', 't', 'rx', 'ry', 'rz', 'cx', 'cy', 'cz', 'ccx', 'swap', 'cswap']
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
description: 'Indices of qubits to apply the gate to',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
parameters: {
|
||||
type: 'array',
|
||||
description: 'Parameters for parameterized gates (e.g., rotation angles)',
|
||||
items: { type: 'number' }
|
||||
},
|
||||
controls: {
|
||||
type: 'array',
|
||||
description: 'Control qubits for controlled operations',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
adjoint: {
|
||||
type: 'boolean',
|
||||
description: 'Apply adjoint (inverse) of the gate',
|
||||
default: false
|
||||
}
|
||||
},
|
||||
required: ['kernel_name', 'gate_name', 'qubits']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for adding measurements to a quantum kernel
|
||||
*/
|
||||
export const addMeasurementTool: Tool = {
|
||||
name: 'add_measurement',
|
||||
description: 'Add quantum measurements to a kernel',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
description: 'Qubits to measure (empty array means measure all)',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
basis: {
|
||||
type: 'string',
|
||||
description: 'Measurement basis',
|
||||
enum: ['Z', 'X', 'Y'],
|
||||
default: 'Z'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for creating common quantum circuits
|
||||
*/
|
||||
export const createCommonCircuitTool: Tool = {
|
||||
name: 'create_common_circuit',
|
||||
description: 'Create commonly used quantum circuits (GHZ, Bell states, QFT, etc.)',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
circuit_type: {
|
||||
type: 'string',
|
||||
description: 'Type of quantum circuit to create',
|
||||
enum: ['bell_pair', 'ghz_state', 'quantum_fourier_transform', 'grover_oracle', 'hadamard_test']
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name for the created kernel'
|
||||
},
|
||||
num_qubits: {
|
||||
type: 'integer',
|
||||
minimum: 2,
|
||||
maximum: 32,
|
||||
description: 'Number of qubits (where applicable)'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Circuit-specific parameters'
|
||||
}
|
||||
},
|
||||
required: ['circuit_type', 'name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for listing available quantum kernels
|
||||
*/
|
||||
export const listQuantumKernelsTool: Tool = {
|
||||
name: 'list_quantum_kernels',
|
||||
description: 'List all available quantum kernels and their metadata',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
detailed: {
|
||||
type: 'boolean',
|
||||
description: 'Include detailed metadata about each kernel',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for visualizing quantum circuits
|
||||
*/
|
||||
export const visualizeCircuitTool: Tool = {
|
||||
name: 'visualize_circuit',
|
||||
description: 'Generate a text-based visualization of a quantum circuit',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to visualize'
|
||||
},
|
||||
format: {
|
||||
type: 'string',
|
||||
description: 'Output format for the visualization',
|
||||
enum: ['text', 'qasm', 'json'],
|
||||
default: 'text'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation functions for the tools
|
||||
*/
|
||||
|
||||
export async function handleCreateQuantumKernel(input: CreateKernelInput) {
|
||||
try {
|
||||
// Validate input
|
||||
const validatedInput = CreateKernelSchema.parse(input);
|
||||
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.createKernel(
|
||||
validatedInput.name,
|
||||
validatedInput.num_qubits,
|
||||
validatedInput.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
logger.info(`Created quantum kernel: ${validatedInput.name} with ${validatedInput.num_qubits} qubits`);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Successfully created quantum kernel '${validatedInput.name}' with ${validatedInput.num_qubits} qubits.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to create quantum kernel');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error creating quantum kernel:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error creating quantum kernel: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleApplyQuantumGate(input: ApplyGateInput) {
|
||||
try {
|
||||
const validatedInput = ApplyGateSchema.parse(input);
|
||||
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.applyGate(
|
||||
validatedInput.kernel_name,
|
||||
validatedInput.gate_name,
|
||||
validatedInput.qubits,
|
||||
validatedInput.parameters,
|
||||
validatedInput.controls,
|
||||
validatedInput.adjoint
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const gateDesc = validatedInput.controls
|
||||
? `controlled ${validatedInput.gate_name}`
|
||||
: validatedInput.gate_name;
|
||||
|
||||
logger.info(`Applied ${gateDesc} gate to kernel ${validatedInput.kernel_name}`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Successfully applied ${gateDesc} gate to qubits [${validatedInput.qubits.join(', ')}] in kernel '${validatedInput.kernel_name}'.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to apply quantum gate');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error applying quantum gate:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error applying quantum gate: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleAddMeasurement(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// For now, measurements are added automatically by CUDA Quantum
|
||||
// This tool documents the measurement intention
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Measurements will be applied to kernel '${input.kernel_name}' in ${input.basis || 'Z'} basis. CUDA Quantum automatically measures all qubits if no explicit measurements are specified.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error adding measurement:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error adding measurement: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleCreateCommonCircuit(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// Create the kernel first
|
||||
const numQubits = input.num_qubits || (input.circuit_type === 'bell_pair' ? 2 : 3);
|
||||
|
||||
let kernelResponse = await bridge.createKernel(input.name, numQubits);
|
||||
if (!kernelResponse.success) {
|
||||
throw new Error(kernelResponse.error || 'Failed to create kernel');
|
||||
}
|
||||
|
||||
// Apply gates based on circuit type
|
||||
switch (input.circuit_type) {
|
||||
case 'bell_pair':
|
||||
await bridge.applyGate(input.name, 'h', [0]);
|
||||
await bridge.applyGate(input.name, 'x', [1], undefined, [0]);
|
||||
break;
|
||||
|
||||
case 'ghz_state':
|
||||
await bridge.applyGate(input.name, 'h', [0]);
|
||||
for (let i = 1; i < numQubits; i++) {
|
||||
await bridge.applyGate(input.name, 'x', [i], undefined, [0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'hadamard_test':
|
||||
await bridge.applyGate(input.name, 'h', [0]);
|
||||
// Additional gates would depend on the operator being tested
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported circuit type: ${input.circuit_type}`);
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Successfully created ${input.circuit_type} circuit named '${input.name}' with ${numQubits} qubits.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error creating common circuit:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error creating common circuit: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleListQuantumKernels(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.listKernels();
|
||||
|
||||
if (response.success) {
|
||||
const kernels = response.kernels || [];
|
||||
const metadata = response.metadata || {};
|
||||
|
||||
if (kernels.length === 0) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: 'No quantum kernels available. Create a kernel first using create_quantum_kernel.'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
let output = `Available quantum kernels (${kernels.length}):\n\n`;
|
||||
|
||||
for (const kernelName of kernels) {
|
||||
const meta = metadata[kernelName] || {};
|
||||
output += `• ${kernelName}\n`;
|
||||
|
||||
if (input.detailed && meta) {
|
||||
output += ` - Qubits: ${meta.num_qubits || 'Unknown'}\n`;
|
||||
output += ` - Parameters: ${meta.parameters?.length || 0}\n`;
|
||||
output += ` - Operations: ${meta.operations?.length || 0}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to list kernels');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error listing quantum kernels:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error listing quantum kernels: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleVisualizeCircuit(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.listKernels();
|
||||
|
||||
if (!response.success || !response.kernels?.includes(input.kernel_name)) {
|
||||
throw new Error(`Kernel '${input.kernel_name}' not found`);
|
||||
}
|
||||
|
||||
const metadata = response.metadata?.[input.kernel_name];
|
||||
if (!metadata) {
|
||||
throw new Error(`No metadata available for kernel '${input.kernel_name}'`);
|
||||
}
|
||||
|
||||
// Generate simple text visualization
|
||||
let circuit = `Quantum Circuit: ${input.kernel_name}\n`;
|
||||
circuit += `Qubits: ${metadata.num_qubits}\n\n`;
|
||||
|
||||
const operations = metadata.operations || [];
|
||||
if (operations.length === 0) {
|
||||
circuit += 'No operations applied yet.\n';
|
||||
} else {
|
||||
circuit += 'Operations:\n';
|
||||
operations.forEach((op: any, index: number) => {
|
||||
const controls = op.controls ? ` (ctrl: ${op.controls.join(',')})` : '';
|
||||
const params = op.parameters ? ` (${op.parameters.join(',')})` : '';
|
||||
circuit += `${index + 1}. ${op.gate.toUpperCase()}${params} → qubits[${op.qubits.join(',')}]${controls}\n`;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: circuit
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error visualizing circuit:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error visualizing circuit: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Export all tools
|
||||
export const quantumCircuitTools: Tool[] = [
|
||||
createQuantumKernelTool,
|
||||
applyQuantumGateTool,
|
||||
addMeasurementTool,
|
||||
createCommonCircuitTool,
|
||||
listQuantumKernelsTool,
|
||||
visualizeCircuitTool
|
||||
];
|
||||
532
src/tools/execution-tools.ts
Archivo normal
532
src/tools/execution-tools.ts
Archivo normal
@@ -0,0 +1,532 @@
|
||||
/**
|
||||
* Quantum Execution Tools for MCP Server
|
||||
* Provides tools for executing quantum circuits and obtaining results
|
||||
*/
|
||||
|
||||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { ExecuteKernelSchema, ExecuteKernelInput } from '../types/index.js';
|
||||
import { getPythonBridge } from '../bridge/python-bridge.js';
|
||||
import { Logger } from '../utils/logger.js';
|
||||
|
||||
const logger = new Logger('QuantumExecutionTools');
|
||||
|
||||
/**
|
||||
* Tool for sampling quantum circuits
|
||||
*/
|
||||
export const sampleQuantumCircuitTool: Tool = {
|
||||
name: 'sample_quantum_circuit',
|
||||
description: 'Sample measurement results from a quantum circuit execution',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to execute'
|
||||
},
|
||||
shots: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100000,
|
||||
default: 1000,
|
||||
description: 'Number of measurement shots'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
description: 'Quantum execution target',
|
||||
default: 'qpp-cpu'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for computing expectation values
|
||||
*/
|
||||
export const observeHamiltonianTool: Tool = {
|
||||
name: 'observe_hamiltonian',
|
||||
description: 'Compute the expectation value of a Hamiltonian using a quantum circuit',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to use'
|
||||
},
|
||||
hamiltonian_terms: {
|
||||
type: 'array',
|
||||
description: 'Pauli terms defining the Hamiltonian',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
paulis: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: ['I', 'X', 'Y', 'Z']
|
||||
}
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
coefficient: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
real: { type: 'number' },
|
||||
imag: { type: 'number' }
|
||||
},
|
||||
required: ['real', 'imag']
|
||||
}
|
||||
},
|
||||
required: ['paulis', 'qubits', 'coefficient']
|
||||
}
|
||||
},
|
||||
shots: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100000,
|
||||
default: 1000,
|
||||
description: 'Number of measurement shots'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name', 'hamiltonian_terms']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for getting quantum state vectors
|
||||
*/
|
||||
export const getQuantumStateTool: Tool = {
|
||||
name: 'get_quantum_state',
|
||||
description: 'Get the quantum state vector from a quantum circuit',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
},
|
||||
format: {
|
||||
type: 'string',
|
||||
enum: ['amplitudes', 'probabilities', 'both'],
|
||||
default: 'amplitudes',
|
||||
description: 'Output format for the state'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for running quantum algorithms
|
||||
*/
|
||||
export const runQuantumAlgorithmTool: Tool = {
|
||||
name: 'run_quantum_algorithm',
|
||||
description: 'Execute quantum algorithms with custom return values',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
shots: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100000,
|
||||
default: 1000,
|
||||
description: 'Number of executions'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for quantum variational optimization
|
||||
*/
|
||||
export const variationalOptimizationTool: Tool = {
|
||||
name: 'variational_optimization',
|
||||
description: 'Perform variational quantum optimization using gradient-based methods',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the parameterized quantum kernel'
|
||||
},
|
||||
hamiltonian_terms: {
|
||||
type: 'array',
|
||||
description: 'Hamiltonian terms for the cost function',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
paulis: {
|
||||
type: 'array',
|
||||
items: { type: 'string', enum: ['I', 'X', 'Y', 'Z'] }
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
coefficient: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
real: { type: 'number' },
|
||||
imag: { type: 'number' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
initial_parameters: {
|
||||
type: 'array',
|
||||
description: 'Initial parameter values',
|
||||
items: { type: 'number' }
|
||||
},
|
||||
optimizer: {
|
||||
type: 'string',
|
||||
enum: ['cobyla', 'l-bfgs-b', 'gradient-descent'],
|
||||
default: 'cobyla',
|
||||
description: 'Optimization algorithm'
|
||||
},
|
||||
max_iterations: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 1000,
|
||||
default: 100,
|
||||
description: 'Maximum optimization iterations'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name', 'hamiltonian_terms', 'initial_parameters']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation functions
|
||||
*/
|
||||
|
||||
export async function handleSampleQuantumCircuit(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// Set target if specified
|
||||
if (input.target) {
|
||||
await bridge.setTarget(input.target);
|
||||
}
|
||||
|
||||
const response = await bridge.sample(
|
||||
input.kernel_name,
|
||||
input.shots || 1000,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
const counts = result.counts || {};
|
||||
const shots = result.shots || input.shots || 1000;
|
||||
|
||||
// Format results
|
||||
let output = `Sampling Results for '${input.kernel_name}':\n\n`;
|
||||
output += `Shots: ${shots}\n`;
|
||||
output += `Results:\n`;
|
||||
|
||||
const sortedStates = Object.entries(counts).sort((a, b) => (b[1] as number) - (a[1] as number));
|
||||
|
||||
for (const [state, count] of sortedStates) {
|
||||
const probability = ((count as number) / shots * 100).toFixed(2);
|
||||
output += ` |${state}⟩: ${count} (${probability}%)\n`;
|
||||
}
|
||||
|
||||
// Calculate entropy
|
||||
const totalCounts = Object.values(counts).reduce((a, b) => (a as number) + (b as number), 0);
|
||||
let entropy = 0;
|
||||
for (const count of Object.values(counts)) {
|
||||
if ((count as number) > 0) {
|
||||
const p = (count as number) / totalCounts;
|
||||
entropy -= p * Math.log2(p);
|
||||
}
|
||||
}
|
||||
|
||||
output += `\nEntropy: ${entropy.toFixed(3)} bits\n`;
|
||||
|
||||
logger.info(`Sampled quantum circuit ${input.kernel_name} with ${shots} shots`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to sample quantum circuit');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error sampling quantum circuit:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error sampling quantum circuit: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleObserveHamiltonian(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.observe(
|
||||
input.kernel_name,
|
||||
input.hamiltonian_terms,
|
||||
input.shots || 1000,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
const expectation = result.expectation;
|
||||
const variance = result.variance;
|
||||
const shots = result.shots || input.shots || 1000;
|
||||
|
||||
let output = `Hamiltonian Expectation Value for '${input.kernel_name}':\n\n`;
|
||||
output += `Expectation Value: ${expectation}\n`;
|
||||
if (variance !== undefined) {
|
||||
output += `Variance: ${variance}\n`;
|
||||
output += `Standard Deviation: ${Math.sqrt(variance).toFixed(6)}\n`;
|
||||
}
|
||||
output += `Shots: ${shots}\n`;
|
||||
|
||||
// Display Hamiltonian terms
|
||||
output += `\nHamiltonian Terms:\n`;
|
||||
input.hamiltonian_terms.forEach((term: any, index: number) => {
|
||||
const coeff = term.coefficient.imag !== 0
|
||||
? `${term.coefficient.real} + ${term.coefficient.imag}i`
|
||||
: `${term.coefficient.real}`;
|
||||
|
||||
const pauli_str = term.paulis.map((p: string, i: number) => `${p}_${term.qubits[i]}`).join(' ⊗ ');
|
||||
output += ` Term ${index + 1}: ${coeff} × (${pauli_str})\n`;
|
||||
});
|
||||
|
||||
logger.info(`Computed expectation value for ${input.kernel_name}: ${expectation}`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to observe Hamiltonian');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error observing Hamiltonian:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error observing Hamiltonian: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleGetQuantumState(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.getState(
|
||||
input.kernel_name,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
const state = result.state || [];
|
||||
const dimension = result.dimension || state.length;
|
||||
|
||||
let output = `Quantum State for '${input.kernel_name}':\n\n`;
|
||||
output += `State Vector Dimension: ${dimension}\n`;
|
||||
|
||||
if (input.format === 'probabilities' || input.format === 'both') {
|
||||
output += `\nProbability Amplitudes:\n`;
|
||||
state.forEach((amplitude: any, index: number) => {
|
||||
const prob = amplitude.real * amplitude.real + amplitude.imag * amplitude.imag;
|
||||
if (prob > 1e-10) { // Only show non-negligible amplitudes
|
||||
const binary = index.toString(2).padStart(Math.log2(dimension), '0');
|
||||
output += ` |${binary}⟩: ${(prob * 100).toFixed(4)}%\n`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (input.format === 'amplitudes' || input.format === 'both') {
|
||||
output += `\nComplex Amplitudes:\n`;
|
||||
state.forEach((amplitude: any, index: number) => {
|
||||
const magnitude = Math.sqrt(amplitude.real * amplitude.real + amplitude.imag * amplitude.imag);
|
||||
if (magnitude > 1e-10) {
|
||||
const binary = index.toString(2).padStart(Math.log2(dimension), '0');
|
||||
const complex_str = amplitude.imag >= 0
|
||||
? `${amplitude.real.toFixed(6)} + ${amplitude.imag.toFixed(6)}i`
|
||||
: `${amplitude.real.toFixed(6)} - ${Math.abs(amplitude.imag).toFixed(6)}i`;
|
||||
output += ` |${binary}⟩: ${complex_str}\n`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate purity and other properties
|
||||
let purity = 0;
|
||||
for (const amplitude of state) {
|
||||
const prob = amplitude.real * amplitude.real + amplitude.imag * amplitude.imag;
|
||||
purity += prob * prob;
|
||||
}
|
||||
|
||||
output += `\nState Properties:\n`;
|
||||
output += ` Purity: ${purity.toFixed(6)}\n`;
|
||||
output += ` Entanglement: ${purity < 0.99 ? 'Entangled' : 'Separable'}\n`;
|
||||
|
||||
logger.info(`Retrieved quantum state for ${input.kernel_name} (dimension: ${dimension})`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to get quantum state');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error getting quantum state:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error getting quantum state: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleRunQuantumAlgorithm(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// This would use CUDA Quantum's run() function for kernels that return values
|
||||
// For now, we'll use sample as a placeholder
|
||||
const response = await bridge.sample(
|
||||
input.kernel_name,
|
||||
input.shots || 1000,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
let output = `Quantum Algorithm Execution Results for '${input.kernel_name}':\n\n`;
|
||||
output += `Executions: ${input.shots || 1000}\n`;
|
||||
output += `Status: Completed Successfully\n`;
|
||||
|
||||
// For actual algorithms, this would show algorithm-specific results
|
||||
output += `\nNote: This is a sample-based execution. For algorithms with custom return values, `;
|
||||
output += `implement the kernel with appropriate return statements in CUDA Quantum.\n`;
|
||||
|
||||
logger.info(`Executed quantum algorithm ${input.kernel_name}`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to run quantum algorithm');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error running quantum algorithm:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error running quantum algorithm: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleVariationalOptimization(input: any) {
|
||||
try {
|
||||
// This is a placeholder for variational optimization
|
||||
// In a full implementation, this would use optimization libraries
|
||||
|
||||
let output = `Variational Optimization for '${input.kernel_name}':\n\n`;
|
||||
output += `Initial Parameters: [${input.initial_parameters.join(', ')}]\n`;
|
||||
output += `Optimizer: ${input.optimizer}\n`;
|
||||
output += `Max Iterations: ${input.max_iterations}\n`;
|
||||
output += `\nNote: Variational optimization requires integration with optimization libraries.\n`;
|
||||
output += `This is a placeholder implementation. In production, this would:\n`;
|
||||
output += `1. Create cost function from Hamiltonian expectation value\n`;
|
||||
output += `2. Use gradient-based or gradient-free optimization\n`;
|
||||
output += `3. Return optimized parameters and minimum energy\n`;
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error in variational optimization:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error in variational optimization: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Export all tools
|
||||
export const quantumExecutionTools: Tool[] = [
|
||||
sampleQuantumCircuitTool,
|
||||
observeHamiltonianTool,
|
||||
getQuantumStateTool,
|
||||
runQuantumAlgorithmTool,
|
||||
variationalOptimizationTool
|
||||
];
|
||||
446
src/tools/hardware-tools.ts
Archivo normal
446
src/tools/hardware-tools.ts
Archivo normal
@@ -0,0 +1,446 @@
|
||||
/**
|
||||
* Hardware Backend Tools for MCP Server
|
||||
* Provides tools for managing quantum execution targets and hardware backends
|
||||
*/
|
||||
|
||||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { SetTargetSchema, QuantumBackends } from '../types/index.js';
|
||||
import { getPythonBridge } from '../bridge/python-bridge.js';
|
||||
import { Logger } from '../utils/logger.js';
|
||||
|
||||
const logger = new Logger('HardwareBackendTools');
|
||||
|
||||
/**
|
||||
* Tool for setting quantum execution target
|
||||
*/
|
||||
export const setQuantumTargetTool: Tool = {
|
||||
name: 'set_quantum_target',
|
||||
description: 'Set the quantum execution target (simulator or hardware backend)',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
target: {
|
||||
type: 'string',
|
||||
description: 'Quantum target name',
|
||||
enum: Object.keys(QuantumBackends)
|
||||
},
|
||||
configuration: {
|
||||
type: 'object',
|
||||
description: 'Target-specific configuration options',
|
||||
properties: {
|
||||
shots: { type: 'integer', minimum: 1, maximum: 100000 },
|
||||
optimization_level: { type: 'integer', minimum: 0, maximum: 3 },
|
||||
api_key: { type: 'string', description: 'API key for hardware providers' },
|
||||
url: { type: 'string', description: 'Custom endpoint URL' },
|
||||
device: { type: 'string', description: 'Specific device name' },
|
||||
noise_model: { type: 'string', description: 'Noise model for simulation' },
|
||||
error_mitigation: { type: 'boolean', description: 'Enable error mitigation' }
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['target']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for listing available quantum backends
|
||||
*/
|
||||
export const listQuantumBackendsTool: Tool = {
|
||||
name: 'list_quantum_backends',
|
||||
description: 'List all available quantum backends and their capabilities',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
category: {
|
||||
type: 'string',
|
||||
enum: ['all', 'simulators', 'hardware'],
|
||||
default: 'all',
|
||||
description: 'Filter backends by category'
|
||||
},
|
||||
detailed: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Include detailed information about each backend'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for getting platform information
|
||||
*/
|
||||
export const getPlatformInfoTool: Tool = {
|
||||
name: 'get_platform_info',
|
||||
description: 'Get information about the current quantum platform and available resources',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for testing backend connectivity
|
||||
*/
|
||||
export const testBackendConnectivityTool: Tool = {
|
||||
name: 'test_backend_connectivity',
|
||||
description: 'Test connectivity to quantum hardware providers',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
backend: {
|
||||
type: 'string',
|
||||
description: 'Backend to test',
|
||||
enum: Object.keys(QuantumBackends)
|
||||
},
|
||||
credentials: {
|
||||
type: 'object',
|
||||
description: 'Credentials for the backend',
|
||||
properties: {
|
||||
api_key: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
username: { type: 'string' },
|
||||
password: { type: 'string' }
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['backend']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for GPU acceleration configuration
|
||||
*/
|
||||
export const configureGpuAccelerationTool: Tool = {
|
||||
name: 'configure_gpu_acceleration',
|
||||
description: 'Configure GPU acceleration for quantum simulations',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
enable: {
|
||||
type: 'boolean',
|
||||
description: 'Enable or disable GPU acceleration'
|
||||
},
|
||||
device_id: {
|
||||
type: 'integer',
|
||||
minimum: 0,
|
||||
description: 'GPU device ID to use'
|
||||
},
|
||||
memory_limit: {
|
||||
type: 'number',
|
||||
description: 'GPU memory limit in GB'
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
enum: ['qpp-gpu', 'density-matrix-gpu'],
|
||||
default: 'qpp-gpu',
|
||||
description: 'GPU-accelerated target'
|
||||
}
|
||||
},
|
||||
required: ['enable']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation functions
|
||||
*/
|
||||
|
||||
export async function handleSetQuantumTarget(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.setTarget(input.target, input.configuration);
|
||||
|
||||
if (response.success) {
|
||||
logger.info(`Set quantum target to: ${input.target}`);
|
||||
|
||||
let output = `Successfully set quantum target to: ${input.target}\n\n`;
|
||||
output += `Description: ${QuantumBackends[input.target as keyof typeof QuantumBackends]}\n`;
|
||||
|
||||
if (input.configuration) {
|
||||
output += `\nConfiguration:\n`;
|
||||
for (const [key, value] of Object.entries(input.configuration)) {
|
||||
if (key !== 'api_key') { // Don't log sensitive information
|
||||
output += ` ${key}: ${value}\n`;
|
||||
} else {
|
||||
output += ` ${key}: [REDACTED]\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to set quantum target');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error setting quantum target:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error setting quantum target: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleListQuantumBackends(input: any) {
|
||||
try {
|
||||
let output = `Available Quantum Backends:\n\n`;
|
||||
|
||||
const simulators = ['qpp-cpu', 'qpp-gpu', 'density-matrix-cpu', 'tensor-network'];
|
||||
const hardware = ['ionq', 'quantinuum', 'quantum_machines', 'infleqtion', 'iqm', 'oqc', 'pasqal'];
|
||||
|
||||
if (input.category === 'all' || input.category === 'simulators') {
|
||||
output += `🖥️ Simulators:\n`;
|
||||
for (const backend of simulators) {
|
||||
if (backend in QuantumBackends) {
|
||||
output += ` • ${backend}: ${QuantumBackends[backend as keyof typeof QuantumBackends]}\n`;
|
||||
|
||||
if (input.detailed) {
|
||||
output += ` - Local execution\n`;
|
||||
output += ` - GPU support: ${backend.includes('gpu') ? 'Yes' : 'No'}\n`;
|
||||
output += ` - Max qubits: ${backend.includes('tensor') ? '40+' : '32'}\n`;
|
||||
output += `\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
output += `\n`;
|
||||
}
|
||||
|
||||
if (input.category === 'all' || input.category === 'hardware') {
|
||||
output += `🔬 Hardware Providers:\n`;
|
||||
for (const backend of hardware) {
|
||||
if (backend in QuantumBackends) {
|
||||
output += ` • ${backend}: ${QuantumBackends[backend as keyof typeof QuantumBackends]}\n`;
|
||||
|
||||
if (input.detailed) {
|
||||
output += ` - Remote execution\n`;
|
||||
output += ` - Authentication required\n`;
|
||||
output += ` - Variable queue times\n`;
|
||||
output += `\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output += `\nTo set a target, use: set_quantum_target\n`;
|
||||
output += `For GPU acceleration, ensure CUDA is installed and use GPU-enabled targets.\n`;
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error listing quantum backends:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error listing quantum backends: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleGetPlatformInfo(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.getPlatformInfo();
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
|
||||
let output = `Quantum Platform Information:\n\n`;
|
||||
output += `Platform Name: ${result.platform_name || 'Unknown'}\n`;
|
||||
output += `Number of QPUs: ${result.num_qpus || 'Unknown'}\n`;
|
||||
output += `Is Simulator: ${result.is_simulator !== undefined ? result.is_simulator : 'Unknown'}\n`;
|
||||
output += `Is Remote: ${result.is_remote !== undefined ? result.is_remote : 'Unknown'}\n`;
|
||||
|
||||
// Add system information
|
||||
output += `\nSystem Information:\n`;
|
||||
output += `Node.js Version: ${process.version}\n`;
|
||||
output += `Platform: ${process.platform}\n`;
|
||||
output += `Architecture: ${process.arch}\n`;
|
||||
|
||||
// GPU information (if available)
|
||||
const cudaDevice = process.env.CUDA_VISIBLE_DEVICES;
|
||||
if (cudaDevice) {
|
||||
output += `CUDA Visible Devices: ${cudaDevice}\n`;
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to get platform information');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error getting platform information:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error getting platform information: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleTestBackendConnectivity(input: any) {
|
||||
try {
|
||||
const backend = input.backend;
|
||||
|
||||
let output = `Testing connectivity to ${backend}...\n\n`;
|
||||
|
||||
// Check if it's a simulator (always available)
|
||||
const simulators = ['qpp-cpu', 'qpp-gpu', 'density-matrix-cpu', 'tensor-network'];
|
||||
|
||||
if (simulators.includes(backend)) {
|
||||
output += `✅ ${backend} is available (local simulator)\n`;
|
||||
|
||||
if (backend.includes('gpu')) {
|
||||
const cudaDevice = process.env.CUDA_VISIBLE_DEVICES;
|
||||
if (cudaDevice) {
|
||||
output += `✅ CUDA device available: ${cudaDevice}\n`;
|
||||
} else {
|
||||
output += `⚠️ CUDA_VISIBLE_DEVICES not set, using default GPU\n`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Hardware backend - check credentials
|
||||
output += `🔗 ${backend} is a hardware provider\n`;
|
||||
|
||||
if (input.credentials?.api_key) {
|
||||
output += `✅ API key provided\n`;
|
||||
} else {
|
||||
output += `❌ API key required for ${backend}\n`;
|
||||
}
|
||||
|
||||
if (input.credentials?.url) {
|
||||
output += `✅ Custom URL provided: ${input.credentials.url}\n`;
|
||||
}
|
||||
|
||||
output += `\nNote: Actual connectivity testing requires valid credentials and active connection.\n`;
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error testing backend connectivity:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error testing backend connectivity: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleConfigureGpuAcceleration(input: any) {
|
||||
try {
|
||||
let output = `GPU Acceleration Configuration:\n\n`;
|
||||
|
||||
if (input.enable) {
|
||||
output += `✅ Enabling GPU acceleration\n`;
|
||||
output += `Target: ${input.target || 'qpp-gpu'}\n`;
|
||||
|
||||
if (input.device_id !== undefined) {
|
||||
output += `GPU Device ID: ${input.device_id}\n`;
|
||||
// Update environment variable
|
||||
process.env.CUDA_VISIBLE_DEVICES = input.device_id.toString();
|
||||
}
|
||||
|
||||
if (input.memory_limit) {
|
||||
output += `Memory Limit: ${input.memory_limit} GB\n`;
|
||||
}
|
||||
|
||||
// Attempt to set GPU target
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.setTarget(input.target || 'qpp-gpu');
|
||||
|
||||
if (response.success) {
|
||||
output += `✅ Successfully configured GPU target\n`;
|
||||
} else {
|
||||
output += `❌ Failed to set GPU target: ${response.error}\n`;
|
||||
}
|
||||
} catch (error) {
|
||||
output += `❌ Error setting GPU target: ${error}\n`;
|
||||
}
|
||||
|
||||
output += `\nNote: Ensure NVIDIA drivers and CUDA toolkit are installed for GPU acceleration.\n`;
|
||||
} else {
|
||||
output += `❌ Disabling GPU acceleration\n`;
|
||||
output += `Falling back to CPU simulation\n`;
|
||||
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
await bridge.setTarget('qpp-cpu');
|
||||
output += `✅ Set target to CPU simulator\n`;
|
||||
} catch (error) {
|
||||
output += `❌ Error setting CPU target: ${error}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error configuring GPU acceleration:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error configuring GPU acceleration: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Export all tools
|
||||
export const hardwareBackendTools: Tool[] = [
|
||||
setQuantumTargetTool,
|
||||
listQuantumBackendsTool,
|
||||
getPlatformInfoTool,
|
||||
testBackendConnectivityTool,
|
||||
configureGpuAccelerationTool
|
||||
];
|
||||
352
src/types/index.ts
Archivo normal
352
src/types/index.ts
Archivo normal
@@ -0,0 +1,352 @@
|
||||
/**
|
||||
* CUDA Quantum MCP Server Type Definitions
|
||||
* Comprehensive type system for quantum computing operations and MCP integration
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
|
||||
// ============================
|
||||
// Core Quantum Types
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Complex number representation for quantum amplitudes
|
||||
*/
|
||||
export interface Complex {
|
||||
real: number;
|
||||
imag: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantum state vector containing complex amplitudes
|
||||
*/
|
||||
export type StateVector = Complex[];
|
||||
|
||||
/**
|
||||
* Quantum measurement result containing bit strings and counts
|
||||
*/
|
||||
export interface MeasurementCounts {
|
||||
[bitString: string]: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantum gate parameter types
|
||||
*/
|
||||
export type GateParameter = number | Complex;
|
||||
|
||||
/**
|
||||
* Quantum register specification
|
||||
*/
|
||||
export interface QuantumRegister {
|
||||
name: string;
|
||||
size: number;
|
||||
indices?: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Single qubit reference
|
||||
*/
|
||||
export interface Qubit {
|
||||
register: string;
|
||||
index: number;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Quantum Operation Types
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Quantum gate operation
|
||||
*/
|
||||
export interface QuantumGate {
|
||||
name: string;
|
||||
qubits: Qubit[];
|
||||
parameters?: GateParameter[];
|
||||
controls?: Qubit[];
|
||||
adjoint?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantum measurement operation
|
||||
*/
|
||||
export interface Measurement {
|
||||
qubits: Qubit[];
|
||||
classical_register?: string;
|
||||
basis?: 'Z' | 'X' | 'Y';
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantum kernel (circuit) definition
|
||||
*/
|
||||
export interface QuantumKernel {
|
||||
name: string;
|
||||
parameters: KernelParameter[];
|
||||
registers: QuantumRegister[];
|
||||
operations: (QuantumGate | Measurement)[];
|
||||
metadata?: {
|
||||
description?: string;
|
||||
author?: string;
|
||||
created?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Kernel parameter definition
|
||||
*/
|
||||
export interface KernelParameter {
|
||||
name: string;
|
||||
type: 'int' | 'float' | 'complex' | 'list[int]' | 'list[float]' | 'list[complex]';
|
||||
default?: any;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Execution Types
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Quantum execution target configuration
|
||||
*/
|
||||
export interface QuantumTarget {
|
||||
name: string;
|
||||
type: 'simulator' | 'hardware';
|
||||
backend: string;
|
||||
configuration?: {
|
||||
shots?: number;
|
||||
noise_model?: string;
|
||||
connectivity?: string;
|
||||
credentials?: Record<string, string>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantum job execution parameters
|
||||
*/
|
||||
export interface ExecutionParams {
|
||||
shots?: number;
|
||||
target?: string;
|
||||
parameters?: Record<string, any>;
|
||||
async?: boolean;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantum execution result
|
||||
*/
|
||||
export interface ExecutionResult {
|
||||
job_id: string;
|
||||
status: 'completed' | 'failed' | 'running' | 'queued';
|
||||
result_type: 'sample' | 'observe' | 'state' | 'run';
|
||||
data: MeasurementCounts | number | StateVector | any[];
|
||||
metadata: {
|
||||
shots?: number;
|
||||
execution_time?: number;
|
||||
target?: string;
|
||||
error?: string;
|
||||
};
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Observable Types
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Pauli string for Hamiltonian terms
|
||||
*/
|
||||
export interface PauliString {
|
||||
paulis: ('I' | 'X' | 'Y' | 'Z')[];
|
||||
qubits: number[];
|
||||
coefficient: Complex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantum Hamiltonian operator
|
||||
*/
|
||||
export interface Hamiltonian {
|
||||
terms: PauliString[];
|
||||
metadata?: {
|
||||
name?: string;
|
||||
description?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Expectation value result
|
||||
*/
|
||||
export interface ExpectationValue {
|
||||
value: number;
|
||||
variance?: number;
|
||||
shots?: number;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// MCP Tool Schemas
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Zod schema for quantum kernel creation
|
||||
*/
|
||||
export const CreateKernelSchema = z.object({
|
||||
name: z.string().min(1),
|
||||
num_qubits: z.number().int().min(1).max(32),
|
||||
parameters: z.array(z.object({
|
||||
name: z.string(),
|
||||
type: z.enum(['int', 'float', 'complex', 'list[int]', 'list[float]', 'list[complex]']),
|
||||
default: z.any().optional(),
|
||||
})).optional(),
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
export type CreateKernelInput = z.infer<typeof CreateKernelSchema>;
|
||||
|
||||
/**
|
||||
* Zod schema for quantum gate application
|
||||
*/
|
||||
export const ApplyGateSchema = z.object({
|
||||
kernel_name: z.string(),
|
||||
gate_name: z.string(),
|
||||
qubits: z.array(z.number().int().min(0)),
|
||||
parameters: z.array(z.number()).optional(),
|
||||
controls: z.array(z.number().int().min(0)).optional(),
|
||||
adjoint: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export type ApplyGateInput = z.infer<typeof ApplyGateSchema>;
|
||||
|
||||
/**
|
||||
* Zod schema for quantum execution
|
||||
*/
|
||||
export const ExecuteKernelSchema = z.object({
|
||||
kernel_name: z.string(),
|
||||
operation: z.enum(['sample', 'observe', 'state', 'run']),
|
||||
shots: z.number().int().min(1).max(100000).optional(),
|
||||
parameters: z.record(z.any()).optional(),
|
||||
hamiltonian: z.array(z.object({
|
||||
paulis: z.array(z.enum(['I', 'X', 'Y', 'Z'])),
|
||||
qubits: z.array(z.number().int().min(0)),
|
||||
coefficient: z.object({
|
||||
real: z.number(),
|
||||
imag: z.number(),
|
||||
}),
|
||||
})).optional(),
|
||||
target: z.string().optional(),
|
||||
});
|
||||
|
||||
export type ExecuteKernelInput = z.infer<typeof ExecuteKernelSchema>;
|
||||
|
||||
/**
|
||||
* Zod schema for target configuration
|
||||
*/
|
||||
export const SetTargetSchema = z.object({
|
||||
target: z.string(),
|
||||
configuration: z.record(z.any()).optional(),
|
||||
});
|
||||
|
||||
export type SetTargetInput = z.infer<typeof SetTargetSchema>;
|
||||
|
||||
// ============================
|
||||
// Hardware Backend Types
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Available quantum hardware backends
|
||||
*/
|
||||
export const QuantumBackends = {
|
||||
// Simulators
|
||||
'qpp-cpu': 'CPU State Vector Simulator',
|
||||
'qpp-gpu': 'GPU State Vector Simulator (cuQuantum)',
|
||||
'density-matrix-cpu': 'CPU Density Matrix Simulator',
|
||||
'tensor-network': 'Tensor Network Simulator',
|
||||
|
||||
// Hardware Providers
|
||||
'ionq': 'IonQ Quantum Processors',
|
||||
'quantinuum': 'Quantinuum H-Series',
|
||||
'quantum_machines': 'Quantum Machines Platform',
|
||||
'infleqtion': 'Infleqtion Quantum Processors',
|
||||
'iqm': 'IQM Quantum Processors',
|
||||
'oqc': 'Oxford Quantum Computing',
|
||||
'pasqal': 'Pasqal Neutral Atom Computers',
|
||||
} as const;
|
||||
|
||||
export type QuantumBackend = keyof typeof QuantumBackends;
|
||||
|
||||
/**
|
||||
* Hardware provider configurations
|
||||
*/
|
||||
export interface HardwareProviderConfig {
|
||||
provider: QuantumBackend;
|
||||
credentials: {
|
||||
api_key?: string;
|
||||
url?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
};
|
||||
configuration: {
|
||||
device?: string;
|
||||
shots?: number;
|
||||
optimization_level?: number;
|
||||
error_mitigation?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Python Bridge Types
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Python function call specification
|
||||
*/
|
||||
export interface PythonCall {
|
||||
module: string;
|
||||
function: string;
|
||||
args: any[];
|
||||
kwargs?: Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Python bridge response
|
||||
*/
|
||||
export interface PythonResponse {
|
||||
success: boolean;
|
||||
result?: any;
|
||||
error?: string;
|
||||
traceback?: string;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Utility Types
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* Server configuration
|
||||
*/
|
||||
export interface ServerConfig {
|
||||
port: number;
|
||||
host: string;
|
||||
python_path: string;
|
||||
default_target: QuantumBackend;
|
||||
max_qubits: number;
|
||||
max_shots: number;
|
||||
gpu_enabled: boolean;
|
||||
log_level: 'debug' | 'info' | 'warn' | 'error';
|
||||
}
|
||||
|
||||
/**
|
||||
* Job status tracking
|
||||
*/
|
||||
export interface JobStatus {
|
||||
id: string;
|
||||
status: 'queued' | 'running' | 'completed' | 'failed';
|
||||
created_at: Date;
|
||||
started_at?: Date;
|
||||
completed_at?: Date;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export default {
|
||||
CreateKernelSchema,
|
||||
ApplyGateSchema,
|
||||
ExecuteKernelSchema,
|
||||
SetTargetSchema,
|
||||
QuantumBackends,
|
||||
};
|
||||
108
src/utils/logger.ts
Archivo normal
108
src/utils/logger.ts
Archivo normal
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Logger utility for the MCP Quantum Server
|
||||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
|
||||
export enum LogLevel {
|
||||
DEBUG = 0,
|
||||
INFO = 1,
|
||||
WARN = 2,
|
||||
ERROR = 3,
|
||||
}
|
||||
|
||||
export interface LoggerConfig {
|
||||
level?: LogLevel;
|
||||
enableColors?: boolean;
|
||||
enableTimestamp?: boolean;
|
||||
component?: string;
|
||||
}
|
||||
|
||||
export class Logger {
|
||||
private level: LogLevel;
|
||||
private enableColors: boolean;
|
||||
private enableTimestamp: boolean;
|
||||
private component: string;
|
||||
|
||||
constructor(component: string = 'MCP-Quantum', config: LoggerConfig = {}) {
|
||||
this.component = component;
|
||||
this.level = config.level ?? LogLevel.INFO;
|
||||
this.enableColors = config.enableColors ?? true;
|
||||
this.enableTimestamp = config.enableTimestamp ?? true;
|
||||
}
|
||||
|
||||
private formatMessage(level: string, message: string, ...args: any[]): string {
|
||||
let formattedMessage = message;
|
||||
|
||||
if (args.length > 0) {
|
||||
formattedMessage += ' ' + args.map(arg =>
|
||||
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
|
||||
).join(' ');
|
||||
}
|
||||
|
||||
let output = '';
|
||||
|
||||
if (this.enableTimestamp) {
|
||||
output += new Date().toISOString() + ' ';
|
||||
}
|
||||
|
||||
if (this.enableColors) {
|
||||
const levelColors = {
|
||||
'DEBUG': chalk.gray,
|
||||
'INFO': chalk.blue,
|
||||
'WARN': chalk.yellow,
|
||||
'ERROR': chalk.red,
|
||||
};
|
||||
|
||||
output += levelColors[level as keyof typeof levelColors](`[${level}]`) + ' ';
|
||||
output += chalk.cyan(`[${this.component}]`) + ' ';
|
||||
output += formattedMessage;
|
||||
} else {
|
||||
output += `[${level}] [${this.component}] ${formattedMessage}`;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
if (this.level <= LogLevel.DEBUG) {
|
||||
console.log(this.formatMessage('DEBUG', message, ...args));
|
||||
}
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
if (this.level <= LogLevel.INFO) {
|
||||
console.log(this.formatMessage('INFO', message, ...args));
|
||||
}
|
||||
}
|
||||
|
||||
warn(message: string, ...args: any[]): void {
|
||||
if (this.level <= LogLevel.WARN) {
|
||||
console.warn(this.formatMessage('WARN', message, ...args));
|
||||
}
|
||||
}
|
||||
|
||||
error(message: string, ...args: any[]): void {
|
||||
if (this.level <= LogLevel.ERROR) {
|
||||
console.error(this.formatMessage('ERROR', message, ...args));
|
||||
}
|
||||
}
|
||||
|
||||
setLevel(level: LogLevel): void {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
getLevel(): LogLevel {
|
||||
return this.level;
|
||||
}
|
||||
}
|
||||
|
||||
// Global logger instance
|
||||
export const logger = new Logger('MCP-Quantum', {
|
||||
level: process.env.LOG_LEVEL === 'debug' ? LogLevel.DEBUG :
|
||||
process.env.LOG_LEVEL === 'warn' ? LogLevel.WARN :
|
||||
process.env.LOG_LEVEL === 'error' ? LogLevel.ERROR :
|
||||
LogLevel.INFO
|
||||
});
|
||||
|
||||
export default Logger;
|
||||
Referencia en una nueva incidencia
Block a user