Bannerlord/Valheim/Lib.GAB Integration Support#59
Merged
pardeike merged 11 commits intopardeike:mainfrom Mar 15, 2026
Merged
Conversation
- Call syncGABPTools() and exposeGABPResources() in setupToolMirroring
- Extract tools from {"tools": [...]} wrapper in ListTools response
- Convert Lib.GAB's parameters array to MCP JSON Schema inputSchema
When using DirectPath or CustomCommand mode with a launcher that spawns the actual game as a separate process (e.g., BLSE for Bannerlord), the direct child process exits after launching the game. IsRunning() would then report false even though the game is running. This adds a fallback to findProcessesByName(StopProcessName) when the direct child process is no longer alive, matching the behavior already used by SteamAppId/EpicAppId modes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On Windows, os.Process.Signal(syscall.Signal(0)) always returns an error because Windows does not support signal 0. This caused IsRunning() to always take the error path even when the child process was alive. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signal(0) is unsupported on Windows and always errors. The previous fix incorrectly returned true when ProcessState was nil, which meant a dead process could be reported as running. Instead, always fall back to isRunningByName() on Windows, which uses tasklist for accurate process detection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of always falling back to process name lookup on Windows, first check if the direct child PID is still alive using tasklist. Only fall back to name lookup if the child is dead (launcher pattern). This matches the Unix Signal(0) behavior more accurately. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace tasklist subprocess with direct OpenProcess+GetExitCodeProcess call on Windows. Extract platform-specific isProcessAlive() into alive_windows.go and alive_unix.go for clean cross-platform support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Pass outputSchema from GABP tools through to MCP Tool struct - Parse Lib.GAB raw tool format (ToolDescriptorRaw) into JSON Schema - Add games.connect and games.call_tool MCP tools - Add context.Context to Client.Connect for caller-controlled timeouts - Wire GABPConnector.AttemptConnection through with context - Implement synchronous tool mirroring in gabp_connector - Add CallToolWithTimeout and sendRequestWithTimeout - Increase GABP connect timeout to 120s for slow-loading games Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds Mount & Blade II: Bannerlord / Lib.GAB compatibility improvements to GABS by hardening process-liveness detection and expanding MCP↔GABP connectivity and tool interoperability.
Changes:
- Context-driven GABP connection retries/timeouts (incl. longer default connect timeout).
- Cross-platform process liveness checks with fallback to
StopProcessNamelookup when launcher child exits. - Lib.GAB tool format support and propagation of
outputSchema, plus new MCP tools (games.connect,games.call_tool) to work around clients that miss dynamic tool updates.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/process/serialized_starter.go | Increases GABP connect timeout and switches connector API to accept context.Context. |
| internal/process/controller.go | Adds PID-based liveness checks and a StopProcessName fallback when child process exits. |
| internal/process/alive_windows.go | Windows implementation of lightweight PID liveness check (OpenProcess/GetExitCodeProcess). |
| internal/process/alive_unix.go | Unix implementation of lightweight PID liveness check (signal 0). |
| internal/mirror/mirror.go | Mirrors GABP tool outputSchema into MCP tool definitions. |
| internal/mcp/types.go | Extends MCP Tool type to include optional outputSchema. |
| internal/mcp/stdio_server.go | Adds games.connect / games.call_tool tools and makes GABP connect use context timeout. |
| internal/mcp/gabp_mirroring_test.go | Updates tests for context-aware Client.Connect. |
| internal/mcp/gabp_connector.go | Makes tool/resource mirroring run synchronously and context-aware connect. |
| internal/mcp/dynamic_tool_discovery_test.go | Updates expected core tool list to include new game-management tools. |
| internal/gabp/client_test.go | Updates client tests for context-aware connect behavior. |
| internal/gabp/client.go | Implements context-driven connect retries; adds Lib.GAB tool parsing + per-request timeout support. |
You can also share your feedback on Copilot code review. Take the survey.
games.tools now includes parameter names, types, and descriptions from inputSchema, plus return field info from outputSchema. This lets AI agents discover the correct argument names for games.call_tool. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- TestBackoffJitter: reduce context timeout from 5s to 500ms and call cancel() explicitly instead of deferring inside the loop - IsRunning: guard c.cmd.Wait() with sync.Once to prevent multiple concurrent Wait calls when IsRunning is called repeatedly - alive_unix: treat EPERM from Signal(0) as "process alive" since it means the process exists but we lack permission to signal it Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- client.go: Thread ctx into handshake via goroutine+select so Connect doesn't block after ctx cancellation. Close connection on handshake failure to prevent leaked goroutines. - stdio_server.go: games.call_tool now accepts both original GABP names (bannerlord.core/ping) and normalized MCP names (bannerlord.bannerlord.core.ping) by stripping the gameId prefix and converting dots back to slashes. - alive_unix.go: Explicitly check ESRCH (no such process) for clarity, with conservative fallback for unknown errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the changes needed to make GABS work with Mount & Blade II: Bannerlord and Lib.GAB.
Improved process detection: Bannerlord launches through BLSE (a mod loader), which means the direct child process exits while the real game keeps running.
IsRunningnow falls back toStopProcessNamelookup when the child process is gone. Process liveness uses platform-specific implementations (Win32OpenProcess/GetExitCodeProcesson Windows,Signal(0)on Unix) instead of spawning external processes.Lib.GAB tool format parsing: Lib.GAB sends tools as a
{"tools": [...]}envelope with flatparametersarrays and C# type names. AddedToolDescriptorRawconversion to JSON SchemainputSchema, and passesoutputSchemaend-to-end from GABP → MCP so AI agents can see tool return types.Context-based GABP connection: Replaced the fixed 5-attempt retry loop in
Client.Connectwithcontext.Context-driven retries. This prevents both premature failure (Bannerlord's mod loading is slow) and infinite hangs. GABP connect timeout increased from 30s to 120s.games.connectandgames.call_toolMCP tools: Claude Code ignorestools/list_changedSSE notifications, so dynamically registered game tools are invisible.games.connectlets the AI manually trigger GABP connection and tool sync.games.call_toolproxies tool calls to the game's GABP server with configurable timeout support for long-running tools likewait_for_screen.Here's the Claude Bug
Synchronous tool mirroring:
setupToolMirroringnow runs synchronously and calls the actualsyncGABPTools/exposeGABPResourcesimplementations (previously a TODO stub running in a goroutine).Companion PR
Lib.GAB side: pardeike/Lib.GAB#10