Skip to main content
Glama

FM8 MCP Server

anythingllm-plugin.js7.12 kB
/** * FM8 MIDI Controller Plugin for AnythingLLM * * This plugin allows AnythingLLM agents to control Native Instruments FM8 * synthesizer via MIDI using a local MCP server. * * Setup: * 1. Start the MCP server: npm run start:http * 2. Place this file in AnythingLLM's custom agent plugins folder * 3. Enable Agent mode in your workspace */ const MCP_SERVER_URL = "http://localhost:3333/mcp"; /** * Helper function to call MCP server tools */ async function callMCPTool(toolName, args) { const response = await fetch(MCP_SERVER_URL, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: Date.now(), method: "tools/call", params: { name: toolName, arguments: args } }) }); if (!response.ok) { throw new Error(`MCP server error: ${response.status}`); } const result = await response.json(); if (result.error) { throw new Error(result.error.message || "MCP tool call failed"); } return result.result; } const plugin = { name: "fm8-controller", startupConfig: { params: {}, }, setup: async function () { // Test connection to MCP server try { const healthCheck = await fetch("http://localhost:3333/health"); if (healthCheck.ok) { return { success: true, message: "FM8 MCP server connected" }; } } catch (error) { return { success: false, message: "FM8 MCP server not running. Start with: npm run start:http" }; } }, plugin: function () { return { name: "FM8 Controller", setup(aibitat) { // Tool 1: Send by CC aibitat.tool( "send_midi_cc", "Send a raw MIDI CC (Control Change) message to FM8. CC numbers range from 0-127, values from 0-127.", { cc: { type: "number", description: "MIDI CC number (0-127)", required: true, }, value: { type: "number", description: "MIDI CC value (0-127)", required: true, }, }, async ({ cc, value }) => { try { const result = await callMCPTool("send_by_cc", { cc, value }); return JSON.stringify({ success: true, cc, value, mappedLabel: result.content?.[0]?.text || "Sent successfully" }); } catch (error) { return JSON.stringify({ success: false, error: error.message }); } } ); // Tool 2: Send by Route aibitat.tool( "send_fm8_route", "Send a FM8 matrix modulation route. Routes connect a source (like LFO1, ENV1) to a destination (like PITCH, CUTOFF). Common sources: LFO1, LFO2, ENV1, ENV2, A, B, C, D. Common destinations: PITCH, CUTOFF, RESONANCE, A, B, C, D, E, F, X, Y, Z.", { source: { type: "string", description: "Modulation source (e.g., 'LFO1', 'ENV1', 'A')", required: true, }, dest: { type: "string", description: "Modulation destination (e.g., 'PITCH', 'CUTOFF', 'B')", required: true, }, value: { type: "number", description: "Modulation amount (0-127)", required: true, }, }, async ({ source, dest, value }) => { try { const result = await callMCPTool("send_by_route", { source, dest, value }); return JSON.stringify({ success: true, route: `${source}->${dest}`, value, message: result.content?.[0]?.text || "Route set successfully" }); } catch (error) { return JSON.stringify({ success: false, error: error.message, tip: "Make sure the route exists. Use list_fm8_mappings to see available routes." }); } } ); // Tool 3: List Mappings aibitat.tool( "list_fm8_mappings", "List all available FM8 matrix mappings, showing routes, labels, CC numbers, and types. Use this to discover what modulation routes are available.", {}, async () => { try { const result = await callMCPTool("list_mappings", {}); const mappings = result.structuredContent?.mappings || []; return JSON.stringify({ success: true, totalMappings: mappings.length, mappings: mappings.slice(0, 20), // Limit to first 20 for readability note: mappings.length > 20 ? `Showing first 20 of ${mappings.length} mappings` : "" }, null, 2); } catch (error) { return JSON.stringify({ success: false, error: error.message }); } } ); // Tool 4: Panic aibitat.tool( "fm8_panic", "Emergency stop! Sends Reset All Controllers, All Sound Off, and All Notes Off to FM8. Use this to immediately silence all sounds.", { channel: { type: "number", description: "MIDI channel (1-16). Optional, defaults to configured channel.", required: false, }, }, async ({ channel }) => { try { const args = channel ? { channel } : {}; const result = await callMCPTool("panic", args); return JSON.stringify({ success: true, message: "Panic sent - all sounds stopped", channel: channel || "default" }); } catch (error) { return JSON.stringify({ success: false, error: error.message }); } } ); // Tool 5: Status aibitat.tool( "fm8_server_status", "Get the current status of the FM8 MCP server, including transport mode, MIDI port, channel, instrument info, and number of available routes.", {}, async () => { try { const result = await callMCPTool("status", {}); const status = result.structuredContent || {}; return JSON.stringify({ success: true, status: { midiPort: status.midiPort, midiChannel: status.channel, instrument: status.instrument, section: status.section, availableRoutes: status.routes, transport: status.transport } }, null, 2); } catch (error) { return JSON.stringify({ success: false, error: error.message }); } } ); }, }; }, }; module.exports = plugin;

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/thesigma1receptor/fm8MCP'

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