Skip to content

MCP server for Godot 4 C# developer workflows - project scaffolding, build automation, and editor tooling.

License

Notifications You must be signed in to change notification settings

jongalloway/godot-csharp-dev-mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Godot C# Dev MCP Server

Build and Test

A Model Context Protocol (MCP) server focused on C#‑based Godot 4 development workflows.
This project provides tools for project scaffolding, build/export automation, static analysis, and editor‑level operations β€” all tailored for C# developers building games with Godot.

This server does not provide runtime debugging or scene‑tree inspection.
For runtime‑focused MCP tooling, see the excellent community project
godot4-runtime-mcp: https://github.com/minghuiliu/godot4-runtime-mcp

πŸ“– Table of Contents


πŸš€ Quick Start

Prerequisites

Installation

# Clone the repository
git clone https://github.com/jongalloway/godot-csharp-dev-mcp.git
cd godot-csharp-dev-mcp

# Build the project
dotnet build --configuration Release

Running the Server

# Run the MCP server (waits for JSON-RPC messages on stdin)
dotnet run --project src/GodotCSharpDevMcp.Server --configuration Release

# OR use the built-in CLI test harness for quick testing
dotnet run --project src/GodotCSharpDevMcp.Server -- --test list_project_files '{}'

Your First Tool Call

Try the list_project_files tool to verify the server is working:

# Using the CLI test harness
dotnet run --project src/GodotCSharpDevMcp.Server -- --test list_project_files '{}'

# Expected output: JSON list of files in current directory

Create a simple C# script:

# Set workspace directory
export GODOT_WORKSPACE_ROOT=/tmp/my-godot-project
mkdir -p $GODOT_WORKSPACE_ROOT

# Create a player script
dotnet run --project src/GodotCSharpDevMcp.Server -- --test create_csharp_script \
  '{"path":"Player.cs","className":"Player","baseType":"Node2D","generateReady":true}'

See the Examples section for complete workflows.


πŸš€ What This Project Is

A developer‑workflow MCP server designed to help AI assistants:

  • Create and scaffold Godot C# projects
  • Generate C# scripts using Roslyn templates
  • Modify scenes and nodes deterministically
  • Run MSBuild and Godot exports
  • Analyze C# code with Roslyn
  • Automate editor‑level tasks
  • Search and inspect project structure

The goal is to make Godot C# development faster, safer, and more reproducible.


🧭 What This Project Is Not

To avoid overlap with existing community work, this project intentionally does not include:

  • Runtime debugging
  • Scene tree introspection during gameplay
  • Log streaming
  • GDScript‑focused tooling

Those scenarios are already well‑served by other MCP servers.

MVP Limitations

The current MVP focuses on file-based workflows. The following features are deferred to post-MVP:

  • Hot-reload workflows: File changes require manual editor refresh
  • Multi-project solutions: Single Godot project per workspace (no shared libraries/multi-project setups)
  • In-editor integration: Server runs outside Godot; cannot directly interact with a running editor instance

See ADR 001: MVP Scope and Architecture for detailed rationale and roadmap.


πŸ“¦ Status

Early development.
See the PRD (or issue #1) for the roadmap, architecture, and planned features.


πŸ“‹ Configuration

The server is configured using environment variables:

Variable Description Default
GODOT_WORKSPACE_ROOT Path to the Godot project workspace Current directory
GODOT_WORKSPACE_READONLY Enable read-only mode (prevents all writes) false
GODOT_MAX_FILE_SIZE_BYTES Maximum file size for read/write operations 10485760 (10 MB)

Example:

# Set workspace to a specific directory
export GODOT_WORKSPACE_ROOT=/home/user/my-godot-game

# Enable read-only mode for safety
export GODOT_WORKSPACE_READONLY=true

# Increase max file size to 50 MB
export GODOT_MAX_FILE_SIZE_BYTES=52428800

Safety Features:

  • Workspace Isolation: All file operations are confined to the configured workspace root
  • Read-Only Mode: Optional mode that prevents all write operations
  • Path Validation: Cross-platform path normalization and boundary checking
  • Size Limits: Configurable limits to prevent memory exhaustion

For detailed information, see Configuration & Safety Documentation.


🎯 Godot .NET / C# Compatibility Notes

This repo uses .NET 10 for the MCP server itself (a standalone tool you run from the command line). That’s generally fine because the server runs outside of Godot.

However, anything that must be loaded/executed by Godot (for example: the generated Godot game project, or any optional editor plugin code) must target the .NET runtime that your chosen Godot version supports.

Practical implications:

  • The MCP server can target newer .NET because Godot does not load the server assembly.
  • Tools that scaffold a Godot C# project should default to a Godot-supported target framework (and optionally a pinned LangVersion), not necessarily net10.0.
  • If/when we add an editor plugin, that plugin (and any shared libraries it loads) should target a Godot-supported framework.

Official references:

πŸ—οΈ Solution Layout

The repository uses a standard .NET solution structure:

GodotCSharpDevMcp.slnx         # Main solution file
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ GodotCSharpDevMcp.Server/   # MCP server host (console app)
β”‚   └── GodotCSharpDevMcp.Core/     # Core library for shared logic
β”œβ”€β”€ tests/
β”‚   └── GodotCSharpDevMcp.Tests/    # Unit tests (xUnit)
└── Directory.Build.props           # Shared build settings

Key Dependencies

  • ModelContextProtocol (0.5.0-preview.1): MCP SDK for implementing the server protocol
  • Microsoft.Extensions.Hosting (10.0.1): Host infrastructure for the MCP server
  • xUnit (2.5.3): Testing framework

All projects target .NET 10 with nullable reference types enabled, implicit usings, and warnings treated as errors for code quality.

Building and Testing

# Restore dependencies
dotnet restore ./GodotCSharpDevMcp.slnx

# Build the solution
dotnet build ./GodotCSharpDevMcp.slnx --configuration Release

# Run tests
dotnet test ./GodotCSharpDevMcp.slnx --configuration Release

Running the Server Locally

The MCP server uses stdio transport to communicate with MCP clients. To run the server:

# Run the server (it will wait for JSON-RPC messages on stdin)
dotnet run --project src/GodotCSharpDevMcp.Server

The server implements the Model Context Protocol and communicates via JSON-RPC 2.0 over stdio. Clients should:

  1. Send an initialize request first
  2. Call tools/list to discover available tools
  3. Use tools/call to invoke tools

Example MCP interaction:

# Send initialize request
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0"}}}' | \
  dotnet run --project src/GodotCSharpDevMcp.Server 2>/dev/null

CLI Test Harness

For local development and smoke testing without requiring an MCP client, the server includes a built-in CLI test harness.

Full CLI Test Harness Documentation

# Basic usage
dotnet run --project src/GodotCSharpDevMcp.Server -- --test <tool_name> <json_input> [log_file]

# List all project files
dotnet run --project src/GodotCSharpDevMcp.Server -- --test list_project_files '{}'

# Read a file
dotnet run --project src/GodotCSharpDevMcp.Server -- --test read_file '{"path":"test.txt"}'

# Write a file
dotnet run --project src/GodotCSharpDevMcp.Server -- --test write_file '{"path":"new-file.txt","content":"Hello, World!"}'

# Run smoke test
bash scripts/cli-smoke-test.sh

Key Features:

  • πŸ”§ Invoke any tool by name with JSON input
  • πŸ“‹ Stable, formatted JSON output for easy diffing
  • πŸ“ Optional log file recording for reproducibility
  • πŸ”’ Same safety guarantees as MCP server (workspace isolation, read-only mode)
  • ⚑ Perfect for local development and automated smoke testing

πŸ› οΈ Tool Catalog

All tools follow a standardized result format for consistent, machine-readable responses.

File System Tools

list_project_files

Enumerate project files with filtering, sorting, and depth control.

Purpose: List relevant files in the workspace with glob pattern support.

Input:

{
  relativeRoot?: string;         // Relative path root (default: workspace root)
  includePatterns?: string[];    // Include glob patterns (e.g., ["**/*.cs"])
  excludePatterns?: string[];    // Additional exclude patterns
  maxDepth?: number;             // Maximum directory depth
  maxResults?: number;           // Maximum number of results
  includeModifiedTime?: boolean; // Include last modified timestamp
}

Output:

{
  entries: Array<{
    relativePath: string;       // Relative path from workspace root
    type: "File" | "Directory"; // Entry type
    sizeBytes?: number;         // File size (null for directories)
    lastModifiedUtc?: string;   // Last modified timestamp (UTC)
  }>;
  totalCount: number;           // Total number of entries found
  isTruncated: boolean;         // Whether results were truncated
}

Example:

# List all C# scripts
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test list_project_files '{"includePatterns":["**/*.cs"]}'

Full documentation

read_file

Read file contents as UTF-8 text with range support.

Purpose: Read files with support for partial reads (byte ranges, line ranges).

Input:

{
  path: string;       // Relative path to file
  offset?: number;    // Byte offset for partial read
  length?: number;    // Number of bytes to read
  startLine?: number; // Starting line number (1-based)
  endLine?: number;   // Ending line number (1-based, inclusive)
}

Output:

{
  content: string;      // File content
  bytesRead: number;    // Bytes read
  totalFileSize: number;// Total file size
  isTruncated: boolean; // Whether content was truncated
}

Example:

# Read entire file
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test read_file '{"path":"Player.cs"}'

# Read lines 10-20
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test read_file '{"path":"Player.cs","startLine":10,"endLine":20}'

Full documentation

write_file

Write UTF-8 text to a file atomically.

Purpose: Safely write files with atomic semantics.

Input:

{
  path: string;                  // Relative path to file
  content: string;               // UTF-8 content to write
  createParentDirectories?: boolean; // Create parent dirs (default: false)
}

Output:

{
  bytesWritten: number;  // Number of bytes written
  absolutePath: string;  // Absolute path to file
}

Example:

dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test write_file '{"path":"test.txt","content":"Hello, World!"}'

Full documentation

search_project

Search project files for text or regex patterns.

Purpose: Find matches across project files with context.

Input:

{
  pattern: string;              // Search pattern (literal or regex)
  isRegex?: boolean;           // Use regex mode (default: false)
  caseSensitive?: boolean;     // Case-sensitive matching (default: true)
  includePatterns?: string[];  // File patterns to include
  excludePatterns?: string[];  // File patterns to exclude
  contextLines?: number;       // Lines of context around matches
  maxResults?: number;         // Maximum number of results
}

Output:

{
  matches: Array<{
    relativePath: string;      // File path
    lineNumber: number;        // Line number of match
    lineContent: string;       // Line content
    contextBefore?: string[];  // Lines before match
    contextAfter?: string[];   // Lines after match
  }>;
  totalMatches: number;        // Total matches found
  isTruncated: boolean;        // Whether results were truncated
}

Example:

# Search for "Player" in all C# files
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test search_project '{"pattern":"Player","includePatterns":["**/*.cs"]}'

Full documentation

Godot Scene Tools

create_scene

Create deterministic Godot 4 scene files (.tscn).

Purpose: Generate valid .tscn files with stable ordering.

Input:

{
  path: string;              // Path to .tscn file
  rootNodeName: string;      // Root node name
  rootNodeType: string;      // Root node type (e.g., "Node2D")
  nodes?: Array<{            // Optional child nodes
    name: string;
    type: string;
    parent: string;
    properties?: {[key: string]: string};
  }>;
}

Output:

{
  absolutePath: string;      // Absolute path to created scene
  bytesWritten: number;      // Bytes written
  nodeCount: number;         // Number of nodes in scene
  message: string;           // Success message
}

Example:

dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test create_scene '{"path":"main.tscn","rootNodeName":"Main","rootNodeType":"Node2D"}'

Full documentation

add_node_to_scene

Add a node to an existing .tscn file deterministically.

Purpose: Modify scene files while preserving structure.

Input:

{
  scenePath: string;              // Path to .tscn file
  parentNodePath: string;         // Parent path ("." for root)
  nodeName: string;               // Name of new node
  nodeType: string;               // Node type (e.g., "Sprite2D")
  properties?: {[key: string]: string}; // Optional properties
}

Output:

{
  scenePath: string;              // Path to modified scene
  nodeName: string;               // Name of added node
  nodeFullPath: string;           // Full path of added node
  message: string;                // Success message
}

Example:

# Add player to root
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test add_node_to_scene \
  '{"scenePath":"main.tscn","parentNodePath":".","nodeName":"Player","nodeType":"CharacterBody2D"}'

Full documentation

C# Code Generation Tools

create_csharp_script

Generate idiomatic Godot 4 C# scripts.

Purpose: Create C# scripts with proper Godot structure.

Input:

{
  path: string;              // Path to .cs file
  className: string;         // Class name
  baseType: string;          // Base type (e.g., "Node2D")
  namespace?: string;        // Optional namespace
  generateReady?: boolean;   // Generate _Ready method
  generateProcess?: boolean; // Generate _Process method
  createParents?: boolean;   // Create parent directories (default: true)
}

Output:

{
  absolutePath: string;      // Absolute path to created script
  bytesWritten: number;      // Bytes written
  className: string;         // Class name
  baseType: string;          // Base type
  message: string;           // Success message
}

Example:

# Create player script with methods
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test create_csharp_script \
  '{"path":"Player.cs","className":"Player","baseType":"CharacterBody2D","generateReady":true,"generateProcess":true}'

Generated output:

using Godot;

public partial class Player : CharacterBody2D
{
	public override void _Ready()
	{
	}

	public override void _Process(double delta)
	{
	}
}

πŸ’‘ Examples

Example 1: Scaffold a Basic Scene and Script

This example creates a simple game scene with a player character.

# Set workspace
export GODOT_WORKSPACE_ROOT=/tmp/my-game
mkdir -p $GODOT_WORKSPACE_ROOT

# Note: Replace with the path where you cloned this repository
# For example: ~/godot-csharp-dev-mcp or /path/to/godot-csharp-dev-mcp
export PROJECT_ROOT=~/godot-csharp-dev-mcp

# 1. Create main scene
dotnet run --project $PROJECT_ROOT/src/GodotCSharpDevMcp.Server -- \
  --test create_scene \
  '{"path":"scenes/main.tscn","rootNodeName":"Main","rootNodeType":"Node2D"}'

# 2. Add a player node to the scene
dotnet run --project $PROJECT_ROOT/src/GodotCSharpDevMcp.Server -- \
  --test add_node_to_scene \
  '{"scenePath":"scenes/main.tscn","parentNodePath":".","nodeName":"Player","nodeType":"CharacterBody2D"}'

# 3. Create the player script
dotnet run --project $PROJECT_ROOT/src/GodotCSharpDevMcp.Server -- \
  --test create_csharp_script \
  '{"path":"scripts/Player.cs","className":"Player","baseType":"CharacterBody2D","namespace":"MyGame","generateReady":true,"generateProcess":true}'

# 4. List all files to verify
dotnet run --project $PROJECT_ROOT/src/GodotCSharpDevMcp.Server -- \
  --test list_project_files '{}'

Example 2: Search and Modify Code

Find all C# files that mention "Player" and read them.

# Search for "Player" in all C# files
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test search_project \
  '{"pattern":"Player","includePatterns":["**/*.cs"],"contextLines":2}'

# Read a specific file
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test read_file '{"path":"scripts/Player.cs"}'

Example 3: Safe Read-Only Mode

Enable read-only mode to inspect a project without modifications.

# Enable read-only mode
export GODOT_WORKSPACE_READONLY=true

# List files (works)
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test list_project_files '{}'

# Try to write (fails with ReadOnlyMode error)
dotnet run --project src/GodotCSharpDevMcp.Server -- \
  --test write_file '{"path":"test.txt","content":"Hello"}'
# Returns: {"success":false,"error":{"code":"ReadOnlyMode","message":"..."}}

πŸ”’ Security & Configuration

The server implements a robust safety model to ensure all operations are deterministic and cannot escape the workspace.

Key Features:

  • Workspace Isolation: All file operations are confined to a configured workspace root
  • Read-Only Mode: Optional mode that prevents all write operations
  • File Size Limits: Configurable limits to prevent memory exhaustion
  • Path Patterns: Allowlist/denylist support using glob patterns
  • Path Validation: Cross-platform path normalization and boundary checking

For detailed information, see Configuration & Safety Documentation.

Known Limitations: Glob pattern ? single-character wildcard is not supported. See issue #70 for details and workarounds.


πŸ“‹ Tool Result Format

All MCP tools in this server use a standardized result envelope to ensure consistent, machine-readable responses.

Success Response

When a tool executes successfully, it returns a result with success: true and the data:

{
  "success": true,
  "data": {
    // Tool-specific response data
  }
}

Error Response

When a tool fails, it returns a result with success: false and an error object:

{
  "success": false,
  "error": {
    "code": "InvalidInput",
    "message": "Human-readable error description",
    "details": {
      // Optional structured details for debugging
    }
  }
}

Error Codes

The server defines standard error codes for common failure scenarios:

Code Description
InvalidInput Invalid input parameters provided to the tool
PathOutsideWorkspace Requested path is outside the workspace boundary
ReadOnlyMode Operation failed because server is in read-only mode
NotFound Requested resource was not found
ExternalToolFailed An external tool (MSBuild, Godot CLI, etc.) failed
InternalError An unexpected internal error occurred

Error Details

The optional details field can contain structured information to help diagnose failures:

{
  "success": false,
  "error": {
    "code": "PathOutsideWorkspace",
    "message": "Path is outside workspace boundary",
    "details": {
      "RequestedPath": "/forbidden/path",
      "WorkspaceRoot": "/allowed/workspace"
    }
  }
}

Note: Stack traces are not included by default. They may be enabled via server configuration for debugging, but production deployments should keep them disabled to avoid leaking sensitive information.


πŸ›  Planned

About

MCP server for Godot 4 C# developer workflows - project scaffolding, build automation, and editor tooling.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages