Skip to main content
Glama

MCP MIDI Bridge

by tezza1971
mcp-client.js10.8 kB
/** * MCP MIDI Bridge Client * * This script provides a simple client to interact with the MCP MIDI Bridge server * running on port 3000. It allows sending NoteSequence JSON to the server and * retrieving the current song. */ const http = require('http'); const fs = require('fs'); const path = require('path'); class McpMidiClient { /** * Create a new MCP MIDI Bridge client * @param {Object} options - Client options * @param {string} options.host - Host address (default: 'localhost') * @param {number} options.port - Port number (default: 3000) */ constructor(options = {}) { this.host = options.host || 'localhost'; this.port = options.port || 3000; console.log(`MCP MIDI Bridge client initialized for ${this.host}:${this.port}`); } /** * Send a NoteSequence to the MCP server * @param {Object} noteSequence - The NoteSequence JSON object * @returns {Promise<Object>} - Response from the server */ async sendNoteSequence(noteSequence) { return new Promise((resolve, reject) => { const data = JSON.stringify(noteSequence); const options = { hostname: this.host, port: this.port, path: '/api/song', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': data.length } }; const req = http.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { try { const parsedData = JSON.parse(responseData); if (res.statusCode >= 200 && res.statusCode < 300) { resolve(parsedData); } else { reject(new Error(`Server responded with status ${res.statusCode}: ${parsedData.error || 'Unknown error'}`)); } } catch (error) { reject(new Error(`Failed to parse response: ${error.message}`)); } }); }); req.on('error', (error) => { reject(new Error(`Request failed: ${error.message}`)); }); req.write(data); req.end(); }); } /** * Get the current song from the MCP server * @returns {Promise<Object>} - The current NoteSequence */ async getCurrentSong() { return new Promise((resolve, reject) => { const options = { hostname: this.host, port: this.port, path: '/api/song', method: 'GET' }; const req = http.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { try { if (res.statusCode === 404) { resolve(null); // No songs found return; } const parsedData = JSON.parse(responseData); if (res.statusCode >= 200 && res.statusCode < 300) { resolve(parsedData); } else { reject(new Error(`Server responded with status ${res.statusCode}: ${parsedData.error || 'Unknown error'}`)); } } catch (error) { reject(new Error(`Failed to parse response: ${error.message}`)); } }); }); req.on('error', (error) => { reject(new Error(`Request failed: ${error.message}`)); }); req.end(); }); } /** * Get information about General MIDI instruments * @returns {Promise<Object>} - General MIDI instrument information */ async getInstruments() { return new Promise((resolve, reject) => { const options = { hostname: this.host, port: this.port, path: '/api/instruments', method: 'GET' }; const req = http.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { try { const parsedData = JSON.parse(responseData); if (res.statusCode >= 200 && res.statusCode < 300) { resolve(parsedData); } else { reject(new Error(`Server responded with status ${res.statusCode}: ${parsedData.error || 'Unknown error'}`)); } } catch (error) { reject(new Error(`Failed to parse response: ${error.message}`)); } }); }); req.on('error', (error) => { reject(new Error(`Request failed: ${error.message}`)); }); req.end(); }); } /** * Get information about General MIDI drum kits * @returns {Promise<Object>} - General MIDI drum kit information */ async getDrums() { return new Promise((resolve, reject) => { const options = { hostname: this.host, port: this.port, path: '/api/drums', method: 'GET' }; const req = http.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { try { const parsedData = JSON.parse(responseData); if (res.statusCode >= 200 && res.statusCode < 300) { resolve(parsedData); } else { reject(new Error(`Server responded with status ${res.statusCode}: ${parsedData.error || 'Unknown error'}`)); } } catch (error) { reject(new Error(`Failed to parse response: ${error.message}`)); } }); }); req.on('error', (error) => { reject(new Error(`Request failed: ${error.message}`)); }); req.end(); }); } /** * Send a NoteSequence from a file to the MCP server * @param {string} filePath - Path to the NoteSequence JSON file * @returns {Promise<Object>} - Response from the server */ async sendNoteSequenceFromFile(filePath) { try { const data = fs.readFileSync(filePath, 'utf8'); const noteSequence = JSON.parse(data); return await this.sendNoteSequence(noteSequence); } catch (error) { throw new Error(`Failed to send NoteSequence from file: ${error.message}`); } } /** * Create a simple C major scale NoteSequence * @returns {Object} - A C major scale NoteSequence */ createCMajorScale() { return { notes: [ { pitch: 60, startTime: 0.0, endTime: 0.5, velocity: 80, instrument: 0, program: 0 }, { pitch: 62, startTime: 0.5, endTime: 1.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 64, startTime: 1.0, endTime: 1.5, velocity: 80, instrument: 0, program: 0 }, { pitch: 65, startTime: 1.5, endTime: 2.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 67, startTime: 2.0, endTime: 2.5, velocity: 80, instrument: 0, program: 0 }, { pitch: 69, startTime: 2.5, endTime: 3.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 71, startTime: 3.0, endTime: 3.5, velocity: 80, instrument: 0, program: 0 }, { pitch: 72, startTime: 3.5, endTime: 4.0, velocity: 80, instrument: 0, program: 0 } ], tempos: [{ time: 0, qpm: 120 }], timeSignatures: [{ time: 0, numerator: 4, denominator: 4 }], totalTime: 4.0 }; } /** * Create a multi-channel NoteSequence with piano, bass, and drums * @returns {Object} - A multi-channel NoteSequence */ createMultiChannelSequence() { return { notes: [ // Piano (Channel 1) { pitch: 60, startTime: 0.0, endTime: 0.5, velocity: 80, instrument: 0, program: 0 }, { pitch: 64, startTime: 0.0, endTime: 0.5, velocity: 80, instrument: 0, program: 0 }, { pitch: 67, startTime: 0.0, endTime: 0.5, velocity: 80, instrument: 0, program: 0 }, { pitch: 62, startTime: 0.5, endTime: 1.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 65, startTime: 0.5, endTime: 1.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 69, startTime: 0.5, endTime: 1.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 60, startTime: 1.0, endTime: 2.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 64, startTime: 1.0, endTime: 2.0, velocity: 80, instrument: 0, program: 0 }, { pitch: 67, startTime: 1.0, endTime: 2.0, velocity: 80, instrument: 0, program: 0 }, // Bass (Channel 2) { pitch: 36, startTime: 0.0, endTime: 1.0, velocity: 100, instrument: 1, program: 33 }, { pitch: 38, startTime: 1.0, endTime: 2.0, velocity: 100, instrument: 1, program: 33 }, // Drums (Channel 10) { pitch: 36, startTime: 0.0, endTime: 0.1, velocity: 100, instrument: 9, program: 0, isDrum: true }, { pitch: 42, startTime: 0.5, endTime: 0.6, velocity: 80, instrument: 9, program: 0, isDrum: true }, { pitch: 38, startTime: 1.0, endTime: 1.1, velocity: 100, instrument: 9, program: 0, isDrum: true }, { pitch: 42, startTime: 1.5, endTime: 1.6, velocity: 80, instrument: 9, program: 0, isDrum: true }, // Strings (Channel 3) { pitch: 72, startTime: 0.0, endTime: 2.0, velocity: 60, instrument: 2, program: 48 } ], tempos: [{ time: 0, qpm: 120 }], timeSignatures: [{ time: 0, numerator: 4, denominator: 4 }], totalTime: 2.0 }; } } // Example usage async function main() { try { // Create a client const client = new McpMidiClient({ port: 3000 }); // Get current song console.log('Fetching current song...'); const currentSong = await client.getCurrentSong(); if (currentSong) { console.log(`Current song has ${currentSong.notes.length} notes`); } else { console.log('No current song found'); } // Send a multi-channel sequence console.log('\nSending multi-channel sequence...'); const multiChannelSequence = client.createMultiChannelSequence(); const response = await client.sendNoteSequence(multiChannelSequence); console.log('Response:', response); console.log('\nDone! The sequence should now be playing in your DAW.'); console.log('The sequence contains:'); console.log('- Piano chords (Channel 1)'); console.log('- Electric bass (Channel 2)'); console.log('- String ensemble (Channel 3)'); console.log('- Drums (Channel 10)'); } catch (error) { console.error('Error:', error.message); console.log('\nMake sure the MCP MIDI Bridge app is running on port 3000.'); } } // Run the example if this file is executed directly if (require.main === module) { main(); } module.exports = McpMidiClient;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tezza1971/mcp-midi'

If you have feedback or need assistance with the MCP directory API, please join our Discord server