@williamzujkowski/strudel-mcp-server
Version:
Advanced MCP server for AI-powered music generation with Strudel.cc
83 lines (82 loc) • 2.62 kB
JavaScript
import { chromium } from 'playwright';
import { AudioAnalyzer } from './AudioAnalyzer.js';
export class StrudelController {
browser = null;
page = null;
analyzer;
isHeadless;
constructor(headless = false) {
this.isHeadless = headless;
this.analyzer = new AudioAnalyzer();
}
async initialize() {
if (this.browser) {
return 'Already initialized';
}
this.browser = await chromium.launch({
headless: this.isHeadless,
args: ['--use-fake-ui-for-media-stream'],
});
const context = await this.browser.newContext({
permissions: ['microphone'],
});
this.page = await context.newPage();
await this.page.goto('https://strudel.cc/', {
waitUntil: 'networkidle',
});
await this.page.waitForSelector('.cm-content', { timeout: 10000 });
await this.analyzer.inject(this.page);
return 'Strudel initialized successfully';
}
async writePattern(pattern) {
if (!this.page)
throw new Error('Not initialized');
await this.page.click('.cm-content');
await this.page.keyboard.press('Control+A');
await this.page.keyboard.type(pattern);
return `Pattern written (${pattern.length} chars)`;
}
async getCurrentPattern() {
if (!this.page)
throw new Error('Not initialized');
return await this.page.evaluate(() => {
const editor = document.querySelector('.cm-content');
return editor?.textContent || '';
});
}
async play() {
if (!this.page)
throw new Error('Not initialized');
try {
await this.page.click('button[title*="play" i]', { timeout: 1000 });
}
catch {
await this.page.keyboard.press('Control+Enter');
}
await this.page.waitForTimeout(500);
return 'Playing';
}
async stop() {
if (!this.page)
throw new Error('Not initialized');
try {
await this.page.click('button[title*="stop" i]', { timeout: 1000 });
}
catch {
await this.page.keyboard.press('Control+Period');
}
return 'Stopped';
}
async analyzeAudio() {
if (!this.page)
throw new Error('Not initialized');
return await this.analyzer.getAnalysis(this.page);
}
async cleanup() {
if (this.browser) {
await this.browser.close();
this.browser = null;
this.page = null;
}
}
}