Skip to content

Add configurable MCP server IP address and port instead of hard coded http://127.0.0.1:50300/sse#25

Open
cervonwong wants to merge 1 commit intoAgentSmithers:masterfrom
cervonwong:feature/configurable-mcp-server-url
Open

Add configurable MCP server IP address and port instead of hard coded http://127.0.0.1:50300/sse#25
cervonwong wants to merge 1 commit intoAgentSmithers:masterfrom
cervonwong:feature/configurable-mcp-server-url

Conversation

@cervonwong
Copy link

Description

This PR adds the ability to configure the MCP server's IP address and port through a plugin UI dialog, replacing the previously hardcoded http://+:50300/sse URL.

Changes

New Files

  • McpServerConfig.cs - Configuration class that stores IP address and port settings, with JSON persistence to mcp_config.json in the plugin directory.
  • McpConfigDialog.cs - Windows Forms dialog for configuring settings via the plugin menu.

Modified Files

  • MCPServer.cs - Updated SimpleMcpServer constructor to accept McpServerConfig parameter for configurable HTTP listener URL.
  • Plugin.Commands.cs - Updated cbStartMCPServer to load and use configuration; added GetMcpServerConfig() and SetMcpServerConfig() helper methods.
  • Plugin.Menus.cs - Added "Configure MCP Server..." menu item under Plugins menu.

Features

  • Persistent Configuration: Settings are saved to mcp_config.json and persist across sessions.
  • UI Configuration Dialog: Accessible via Plugins → Configure MCP Server...
image * **Live URL Preview:** Dialog shows real-time preview of the configured URL. image * **Input Validation:** Validates IP address format before saving.

Supported IP Address Values

Value Behavior
+ or * Listen on all interfaces (requires admin privileges or urlacl)
127.0.0.1 or localhost Local-only access (no admin required)
Specific IP (e.g., 192.168.1.100) Listen on specific network interface

Usage

  1. Open x64dbg with the plugin loaded.
  2. Go to Plugins → Configure MCP Server...
  3. Enter desired IP address and port.
  4. Click Save.
  5. Restart the MCP server (Stop then Start) for changes to take effect.

Testing

  • Build succeeds with no errors
  • Configuration dialog opens and displays correctly
  • Settings persist after closing and reopening x64dbg
  • Server starts with configured IP/port
image image

Breaking Changes

None. Default values (+:50300) match the previous hardcoded behavior.

@cervonwong cervonwong marked this pull request as ready for review December 8, 2025 05:59
Copilot AI review requested due to automatic review settings December 8, 2025 05:59
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds configurable MCP server IP address and port settings to replace the hardcoded http://+:50300/sse URL. The implementation introduces a configuration dialog, persistent JSON-based settings storage, and helper methods for managing the configuration.

Key Changes:

  • New configuration infrastructure with JSON persistence to mcp_config.json
  • Windows Forms dialog for user-friendly configuration management with real-time URL preview
  • Integration of configuration loading into server startup and menu system

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
McpServerConfig.cs New configuration class handling IP/port settings, JSON persistence, and validation logic with default values (+:50300)
McpConfigDialog.cs New Windows Forms dialog providing UI for IP/port configuration with live URL preview and input validation
Plugin.Menus.cs Added "Configure MCP Server..." menu item with STA thread handling for dialog display
Plugin.Commands.cs Updated server initialization to load configuration; added helper methods for config management; includes unrelated GetCallStack refactoring
MCPServer.cs Modified constructors to accept McpServerConfig parameter and use configurable URLs for HTTP listener

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +72 to +93
var t = new Thread(() =>
{
using (var dialog = new McpConfigDialog(config))
{
if (dialog.ShowDialog() == DialogResult.OK)
{
// Update and save configuration
config.IpAddress = dialog.IpAddress;
config.Port = dialog.Port;
Plugin.SetMcpServerConfig(config);

MessageBox.Show(
$"Configuration saved.\n\nNew URL: {config.GetDisplayUrl()}\n\nPlease restart the MCP server for changes to take effect.",
"MCP Server Configuration",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thread is being joined synchronously (t.Join()), which blocks the calling thread until the dialog is closed. This defeats the purpose of creating a separate thread. Consider using Application.Run() directly on the current thread if it's already STA, or check the apartment state before creating a new thread. If you must use a new thread, consider whether blocking the caller is the intended behavior.

Copilot uses AI. Check for mistakes.
/// </summary>
public string GetDisplayUrl()
{
string displayIp = IpAddress == "+" ? "127.0.0.1" : IpAddress;
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IP address validation accepts "" as valid, but the GetDisplayUrl() method only handles "+" for display conversion. When "" is used, it will be displayed as-is in the URL ("http://:port/sse"), which is not a valid connectable URL. The display conversion logic should also handle "" the same way as "+".

Suggested change
string displayIp = IpAddress == "+" ? "127.0.0.1" : IpAddress;
string displayIp = (IpAddress == "+" || IpAddress == "*") ? "127.0.0.1" : IpAddress;

Copilot uses AI. Check for mistakes.
Comment on lines +165 to +169
private void UpdateUrlPreview()
{
string ip = string.IsNullOrWhiteSpace(txtIpAddress.Text) ? "+" : txtIpAddress.Text.Trim();
string displayIp = (ip == "+" || ip == "*") ? "127.0.0.1" : ip;
lblCurrentUrl.Text = $"http://{displayIp}:{(int)numPort.Value}/sse";
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL preview conversion logic only handles "+" but should also handle "", which is also accepted as a valid wildcard address. When "" is entered, it should be displayed as "127.0.0.1" just like "+".

Copilot uses AI. Check for mistakes.
Comment on lines +124 to +127
public static void SetMcpServerConfig(McpServerConfig config)
{
GMcpServerConfig = config;
config.Save();
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The static GMcpServerConfig field is accessed and modified without synchronization from both the menu thread (via ConfigureMCPServer) and command thread (via cbStartMCPServer). This creates a potential race condition. Consider adding lock protection or using a thread-safe pattern for accessing this shared state.

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +105
public void Save()
{
try
{
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(this);

// Ensure directory exists
var dir = Path.GetDirectoryName(ConfigPath);
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}

File.WriteAllText(ConfigPath, json);
Console.WriteLine($"[McpServerConfig] Configuration saved to: {ConfigPath}");
}
catch (Exception ex)
{
Console.WriteLine($"[McpServerConfig] Error saving config: {ex.Message}");
}
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The configuration file write operation (File.WriteAllText) could fail due to file system permissions, disk space, or file locking issues. However, exceptions are caught and logged, which is a good practice. Consider whether the user should be notified with a visible error message (MessageBox) in addition to console logging, since configuration save failures during the interactive dialog flow may otherwise go unnoticed by the user.

Copilot uses AI. Check for mistakes.
Comment on lines +1369 to 1375
IntPtr ptrModule = IntPtr.Zero;
IntPtr ptrLabel = IntPtr.Zero;
IntPtr ptrComment = IntPtr.Zero;
BRIDGE_ADDRINFO_NATIVE addrInfo = new BRIDGE_ADDRINFO_NATIVE(); // Must be NATIVE struct

for (int i = 0; i < callstackFrames.Count; i++)
{
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving the memory allocation outside the loop creates a resource leak. The IntPtr variables are allocated once but freed in every iteration, and the final iteration's allocated memory will never be freed. The original code (allocating inside the loop) ensures all allocated memory is freed in the corresponding finally block.

Suggested change
IntPtr ptrModule = IntPtr.Zero;
IntPtr ptrLabel = IntPtr.Zero;
IntPtr ptrComment = IntPtr.Zero;
BRIDGE_ADDRINFO_NATIVE addrInfo = new BRIDGE_ADDRINFO_NATIVE(); // Must be NATIVE struct
for (int i = 0; i < callstackFrames.Count; i++)
{
BRIDGE_ADDRINFO_NATIVE addrInfo = new BRIDGE_ADDRINFO_NATIVE(); // Must be NATIVE struct
for (int i = 0; i < callstackFrames.Count; i++)
{
IntPtr ptrModule = IntPtr.Zero;
IntPtr ptrLabel = IntPtr.Zero;
IntPtr ptrComment = IntPtr.Zero;

Copilot uses AI. Check for mistakes.
Top = 20,
Width = 80,
TextAlign = ContentAlignment.MiddleRight
};
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'Label' is created but not disposed.

Suggested change
};
};
Controls.Add(lblIp);

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +69
var lblIpHelp = new Label
{
Text = "(+, *, localhost, or IP)",
Left = 285,
Top = 20,
Width = 110,
ForeColor = Color.Gray,
Font = new Font(Font.FontFamily, 8)
};
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'Label' is created but not disposed.

Copilot uses AI. Check for mistakes.
Comment on lines +72 to +79
var lblPort = new Label
{
Text = "Port:",
Left = 15,
Top = 55,
Width = 80,
TextAlign = ContentAlignment.MiddleRight
};
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'Label' is created but not disposed.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +101
var lblUrlTitle = new Label
{
Text = "Server URL:",
Left = 15,
Top = 95,
Width = 80,
TextAlign = ContentAlignment.MiddleRight
};
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'Label' is created but not disposed.

Copilot uses AI. Check for mistakes.
@cervonwong cervonwong mentioned this pull request Dec 8, 2025
@AgentSmithers
Copy link
Owner

Thank you, I will review the change and merge it if I don't have any follow up questions.

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.

2 participants