Skip to content

[Experimental] Add Multi-Instance Support and Log Output Cleanup#56

Open
tylerstraub wants to merge 5 commits intoCoding-Solo:mainfrom
tylerstraub:feature/multi-instance-support
Open

[Experimental] Add Multi-Instance Support and Log Output Cleanup#56
tylerstraub wants to merge 5 commits intoCoding-Solo:mainfrom
tylerstraub:feature/multi-instance-support

Conversation

@tylerstraub
Copy link

Overview

This PR adds experimental support for running multiple Godot instances simultaneously, along with improvements to log output formatting. This work was developed to address a specific use case (multiplayer game development with dedicated server + multiple clients) and is presented here as a potential contribution for maintainers to consider.

Status: Experimental / Proof of Concept
Testing: Limited to ad-hoc use case; not fully tested across all scenarios
Recommendation: Review and consider for future main branch integration

Motivation

The current implementation supports running a single Godot instance at a time. For multiplayer game development workflows, there's a need to:

  • Launch a dedicated server instance
  • Launch multiple client instances simultaneously
  • Manage and monitor each instance independently
  • Pass custom command-line arguments to each instance

This PR extends the MCP server to support these workflows while maintaining backward compatibility.

Changes

Core Features

  1. Multi-Instance Process Management

    • Replaced single activeProcess with Map<string, GodotProcess> to track multiple instances
    • Each instance has a unique instanceId (user-provided or auto-generated)
    • Process state tracking: id, projectPath, scene, startedAt, isRunning
  2. Enhanced run_project Tool

    • New instanceId parameter for unique identifiers
    • New args parameter to pass command-line arguments (e.g., --server, --headless, profile=X, port=Y)
    • Validates duplicate instance IDs before launching
    • Auto-generates IDs when not provided (instance_1, instance_2, etc.)
  3. Enhanced get_debug_output Tool

    • New optional instanceId parameter to get output for a specific instance
    • Returns output for all instances when instanceId is omitted
    • Includes instance metadata (project path, scene, start time, running status)
  4. Enhanced stop_project Tool

    • New optional instanceId parameter to stop a specific instance
    • Stops all instances when instanceId is omitted
    • Returns final output and errors for stopped instances
  5. New list_processes Tool

    • Lists all running Godot instances with status
    • Shows instance ID, project path, scene, start time, running status, and output/error line counts

Log Output Improvements

  • Strips carriage returns (\r) from output
  • Filters empty lines
  • Trims trailing whitespace
  • Redirects debug output to stderr instead of stdout to prevent MCP protocol interference
  • Cleaner, more readable console output

Technical Details

Modified Files:

  • src/index.ts: Core implementation changes (371 lines changed: +304, -67)
  • README.md: Documentation updates (37 lines changed: +35, -2)

Key Implementation Changes:

  • GodotProcess interface extended with id, projectPath, scene, startedAt, isRunning
  • GodotServer class now uses Map<string, GodotProcess> instead of single process
  • Added nextInstanceId counter for auto-generation
  • Updated logDebug() to use console.error() for stderr output
  • Enhanced process event handlers to maintain process info after exit for debugging

Use Cases

Multiplayer Development Workflow

// 1. Launch dedicated server
run_project({
  projectPath: "/path/to/project",
  instanceId: "server",
  args: ["--", "--server", "port=8080", "--headless"]
})

// 2. Launch client instances
run_project({
  projectPath: "/path/to/project",
  instanceId: "client1",
  args: ["--", "profile=player1", "ip=127.0.0.1", "port=8080"]
})

run_project({
  projectPath: "/path/to/project",
  instanceId: "client2",
  args: ["--", "profile=player2", "ip=127.0.0.1", "port=8080"]
})

// 3. Monitor all instances
list_processes()

// 4. Get server-specific logs
get_debug_output({ instanceId: "server" })

// 5. Stop specific client
stop_project({ instanceId: "client1" })

Backward Compatibility

  • All new parameters are optional
  • Existing tool calls without instanceId continue to work
  • get_debug_output and stop_project without instanceId operate on all instances (maintains previous behavior when only one instance exists)

Testing Status

Tested Scenarios:

  • Single instance launches (backward compatibility)
  • Multiple simultaneous instances (server + clients)
  • Instance-specific operations (get output, stop)
  • Auto-generated vs. user-provided instance IDs
  • Custom command-line arguments
  • Log output formatting and cleanup

Not Yet Tested:

  • Edge cases with many concurrent instances
  • Error handling in various failure scenarios
  • Cross-platform compatibility (tested primarily on Windows)
  • Long-running instance stability
  • Resource cleanup in all edge cases

Documentation

  • Updated README.md Features section with multi-instance capabilities
  • Added list_processes to autoApprove configuration examples
  • Added example prompts for multi-instance workflows
  • Added "Multi-Instance Support" section with detailed usage examples
  • Documented multiplayer development workflow

Breaking Changes

None. All changes are backward compatible.

Next Steps / Considerations

This PR is presented as experimental work that has been useful for a specific development workflow. Before considering for main branch integration, maintainers may want to:

  1. Review the architecture and implementation approach
  2. Consider additional testing scenarios
  3. Evaluate cross-platform compatibility
  4. Assess resource management and cleanup
  5. Consider API design and naming conventions
  6. Review documentation completeness

Feedback and suggestions are welcome. This is intended as a starting point for discussion rather than a final implementation.

- Replace single activeProcess with Map-based activeProcesses for concurrent instance management
- Add instanceId parameter to run_project, get_debug_output, and stop_project tools
- Add args parameter to run_project for passing command-line arguments to Godot
- Add list_processes tool to view all running instances with status
- Add isRunning flag to GodotProcess interface for status tracking
- Redirect all debug/log output to console.error (stderr) to prevent MCP protocol interference
- Clean log output: strip carriage returns, filter empty lines, trim whitespace
- Improve process cleanup to handle multiple instances
- Add nextInstanceId counter for auto-generating instance IDs
- Retain process output after exit for debugging purposes

This enables MMORPG development workflows where multiple Godot instances
(server + multiple clients) can run simultaneously with proper isolation
and management.
- Update the description for the 'list_processes' tool to clarify it tracks both running and recently exited instances.
- Improve instance ID validation to allow reuse of IDs for exited processes.
- Ensure only running processes are killed during stop operations, while still tracking all instances.
- Add logging for cleaning up exited processes to aid in debugging.
@tylerstraub
Copy link
Author

So I've been using this branch heavily and I can tell you at least from a user perspective its working really really well.

The agent has been able to manage multiple processes (my workflow requires 2 clients, 1 server) and tail them individually by its own instance name it creates at runtime. It also able to use the "all" variants to take down or start up multiple processes at once.

The only thing I added not covered here was add some additional re-enforcement in my AGENTS.md around the workflow and an additional parameter to take down, or being up instances with a single tool call instead of having to do individual calls.

Full disclosure though this was very loosely planned by me and executed fully by a Cursor IDE agent in like 20 minutes and therefore probably not suitable for main branch. I just primarily wanted to demonstrate the need and a possible approach here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant