Skip to main content
Glama
williamzujkowski

Strudel MCP Server

write

Write TidalCycles/Strudel music patterns to the editor with options for auto-playback and validation to control browser-based music generation.

Instructions

Write pattern to editor with optional auto-play and validation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
patternYesPattern code
auto_playNoStart playback immediately after writing (default: false)
validateNoValidate pattern before writing (default: true)

Implementation Reference

  • Tool registration and schema definition for 'write' tool, including input schema with pattern (required), auto_play, and validate options.
    {
      name: 'write',
      description: 'Write pattern to editor with optional auto-play and validation',
      inputSchema: {
        type: 'object',
        properties: {
          pattern: { type: 'string', description: 'Pattern code' },
          auto_play: { type: 'boolean', description: 'Start playback immediately after writing (default: false)' },
          validate: { type: 'boolean', description: 'Validate pattern before writing (default: true)' }
        },
        required: ['pattern']
      }
    },
  • MCP tool handler for 'write': validates input, optionally validates pattern, writes via writePatternSafe, optionally auto-plays.
    case 'write':
      InputValidator.validateStringLength(args.pattern, 'pattern', 10000, true);
    
      // Validate pattern if requested (default: true) - Issue #40
      if (args.validate !== false && this.isInitialized && typeof this.controller.validatePattern === 'function') {
        try {
          const validation = await this.controller.validatePattern(args.pattern);
          if (validation && !validation.valid) {
            return {
              success: false,
              errors: validation.errors,
              warnings: validation.warnings,
              suggestions: validation.suggestions,
              message: `Pattern validation failed: ${validation.errors.join('; ')}`
            };
          }
        } catch (e) {
          // Validation failed, but we can still try to write
          this.logger.warn('Pattern validation threw error, continuing with write');
        }
      }
    
      const writeResult = await this.writePatternSafe(args.pattern);
    
      // Auto-play if requested - Issue #38
      if (args.auto_play && this.isInitialized) {
        await this.controller.play();
        return `${writeResult}. Playing.`;
      }
    
      return writeResult;
  • Helper method writePatternSafe: handles uninitialized state by caching pattern, otherwise delegates to controller.writePattern.
    private async writePatternSafe(pattern: string): Promise<string> {
      if (!this.isInitialized) {
        // Store the pattern for later use
        const id = `pattern_${Date.now()}`;
        this.generatedPatterns.set(id, pattern);
        return `Pattern generated (initialize Strudel to use it): ${pattern.substring(0, 50)}...`;
      }
      
      return await this.controller.writePattern(pattern);
    }
  • Core implementation of writePattern: uses Playwright to manipulate CodeMirror editor in strudel.cc browser page, verifies write, updates cache.
    async writePattern(pattern: string): Promise<string> {
      if (!this._page) throw new Error('Browser not initialized. Run init tool first.');
    
      // Invalidate cache before write to prevent stale reads
      this.invalidateCache();
    
      // Use evaluate for faster direct manipulation
      const success = await this._page.evaluate((newPattern) => {
        const editor = document.querySelector('.cm-content') as HTMLElement;
        if (editor) {
          const view = (editor as any).__view;
          if (view) {
            view.dispatch({
              changes: { from: 0, to: view.state.doc.length, insert: newPattern }
            });
            return true;
          }
        }
        return false;
      }, pattern);
    
      if (!success) {
        throw new Error('Failed to write pattern - editor not found or view unavailable');
      }
    
      // Verify the write by reading back from browser (fixes cache sync issues)
      const verified = await this._page.evaluate(() => {
        const editor = document.querySelector('.cm-content') as HTMLElement;
        if (editor) {
          const view = (editor as any).__view;
          if (view && view.state && view.state.doc) {
            return view.state.doc.toString();
          }
        }
        return null;
      });
    
      // Update cache with verified content
      this.editorCache = verified || pattern;
      this.cacheTimestamp = Date.now();
    
      // Log warning if verification failed
      if (verified === null) {
        this.logger.warn('Pattern write verification failed - using input pattern for cache');
      }
    
      return `Pattern written (${pattern.length} chars)`;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It mentions 'write' (implying mutation) and optional 'auto-play' and 'validation' behaviors, but doesn't disclose critical behavioral traits: whether this overwrites existing content, what permissions are needed, error handling for invalid patterns, or what happens when auto-play is enabled. The description adds some context but leaves significant gaps for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action ('write pattern to editor') and mentions key optional features. Every word earns its place with zero waste or redundancy. It's appropriately sized for a tool with three well-documented parameters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no annotations and no output schema, the description is insufficient. It doesn't explain what 'write' means operationally (overwrite? append?), doesn't describe the return value or error conditions, and provides minimal behavioral context. Given the complexity of modifying editor content and the lack of structured safety information, this description leaves too many questions unanswered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters thoroughly. The description mentions 'optional auto-play and validation' which aligns with the schema but adds no additional semantic meaning beyond what's in the parameter descriptions. This meets the baseline expectation when schema coverage is high.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('write') and resource ('pattern to editor'), making the purpose understandable. However, it doesn't explicitly differentiate this tool from similar siblings like 'append', 'insert', or 'replace', which might also modify editor content. The description is specific about what gets written (pattern) but lacks sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. With siblings like 'append', 'insert', 'replace', and 'compose' that might also modify editor content, there's no indication of when 'write' is preferred or what distinguishes it. The optional parameters hint at some use cases but don't provide explicit usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/williamzujkowski/strudel-mcp-server'

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