Skip to content

Refactor safe-outputs MCP server tools: Extract to JSON and pre-filter in Go#1486

Closed
Copilot wants to merge 7 commits intomainfrom
copilot/refactor-tools-json-payload
Closed

Refactor safe-outputs MCP server tools: Extract to JSON and pre-filter in Go#1486
Copilot wants to merge 7 commits intomainfrom
copilot/refactor-tools-json-payload

Conversation

Copy link
Contributor

Copilot AI commented Oct 10, 2025

Problem

The safe-outputs MCP server had tool definitions hardcoded in JavaScript (ALL_TOOLS array in safe_outputs_mcp_server.cjs). This meant:

  • Tool filtering happened at runtime in JavaScript
  • Tool definitions were duplicated between Go configuration and JavaScript implementation
  • Adding or modifying tools required changes in multiple places
  • No type safety for tool definitions

Solution

This PR refactors the architecture to extract tool definitions into a separate JSON file and perform filtering in Go before passing to the JavaScript MCP server. Legacy support has been completely removed - the MCP server now requires the GITHUB_AW_SAFE_OUTPUTS_TOOLS environment variable.

Architecture Changes

Before:

// JavaScript (safe_outputs_mcp_server.cjs)
const ALL_TOOLS = [/* 11 tool definitions hardcoded here */];

// Filter at runtime based on config
ALL_TOOLS.forEach(tool => {
  if (Object.keys(safeOutputsConfig).find(config => normTool(config) === tool.name)) {
    TOOLS[tool.name] = tool;
  }
});

After:

// Go (safe_outputs_tools.go)
//go:embed data/safe_outputs_tools.json
var safeOutputsToolsJSON string

// Pre-filter tools based on configuration
filteredToolsJSON := compiler.GenerateFilteredToolsJSON(workflowData)
// Pass to JavaScript via environment variable
// JavaScript (safe_outputs_mcp_server.cjs)
const toolsEnv = process.env.GITHUB_AW_SAFE_OUTPUTS_TOOLS;

if (!toolsEnv) {
  throw new Error("GITHUB_AW_SAFE_OUTPUTS_TOOLS environment variable is required");
}

const PREDEFINED_TOOLS = JSON.parse(toolsEnv); // Pre-filtered by Go

// Log filtered tools for debugging
console.error(`[${SERVER_INFO.name}] Filtered tools:\n${JSON.stringify(TOOLS, null, 2)}`);

Key Changes

  1. New JSON file (pkg/workflow/data/safe_outputs_tools.json):

    • Single source of truth for all 11 tool definitions
    • Includes metadata like hasHandler flag for tools needing custom handlers
    • Easy to version and maintain
  2. Go filtering logic (pkg/workflow/safe_outputs_tools.go):

    • Embeds JSON file using //go:embed
    • Provides type-safe access via SafeOutputToolDefinition struct
    • Pre-filters tools based on safe-outputs configuration
    • Generates JSON payload for JavaScript
  3. Environment variable (GITHUB_AW_SAFE_OUTPUTS_TOOLS):

    • Required - MCP server will fail if not provided
    • Passes pre-filtered tools from Go to JavaScript
    • Set in both Setup MCPs step and Claude MCP configuration
    • Reduces JSON payload size (only enabled tools)
  4. JavaScript requirements:

    • Reads pre-filtered tools from environment variable
    • Dynamically attaches handlers based on hasHandler flag
    • No legacy fallback - ALL_TOOLS array completely removed (~238 lines)
    • Debug logging - Logs filtered tools in pretty-printed JSON format (2-space indentation) to stderr for debugging

Benefits

  • Separation of concerns: Tool definitions separate from filtering logic
  • Performance: Filtering happens once in Go instead of every MCP server initialization
  • Type safety: Go structs provide compile-time validation
  • Maintainability: Single JSON file to update when adding/modifying tools
  • Smaller payloads: Only enabled tools passed to JavaScript (typically 2-4 tools instead of 11)
  • Cleaner codebase: No legacy code paths or backward compatibility overhead
  • Clear errors: Explicit error messages when environment variable is missing
  • Better debugging: Filtered tools are logged in readable format for troubleshooting

Example

For a workflow with only create-pull-request and upload-assets configured:

# Before: JavaScript receives all 11 tools and filters at runtime

# After: JavaScript receives only 3 pre-filtered tools
env:
  GITHUB_AW_SAFE_OUTPUTS_TOOLS: '{"create_pull_request":{...},"upload_asset":{...},"missing_tool":{...}}'

The MCP server will log on startup:

[safe-outputs-mcp-server] Filtered tools:
{
  "create_pull_request": { ... },
  "upload_asset": { ... },
  "missing_tool": { ... }
}

Testing

  • ✅ All existing tests pass (264+ tests)
  • ✅ New comprehensive tests for JSON parsing and filtering
  • ✅ MCP server tests updated to provide required environment variable
  • ✅ All 90 workflows recompile successfully
  • ✅ Manual verification of tool filtering in compiled workflows
  • ✅ Manual verification of debug logging output
  • make agent-finish validation passes
Original prompt

Refactor the TOOLS JSON payload in the safe output mcp server javascript into a separate file, embedded in .go. The .go compiler should update the safe outputs mcp server configuration step to pass the configuration as an environment variable (pre-filtered)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits October 10, 2025 20:46
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
}

// Legacy ALL_TOOLS array - kept for backward compatibility when env var not provided
const ALL_TOOLS = [
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot remove legacy support

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed legacy support. The ALL_TOOLS array and fallback logic have been completely removed from safe_outputs_mcp_server.cjs. The server now requires GITHUB_AW_SAFE_OUTPUTS_TOOLS environment variable and will throw an error if it's not provided. Tests updated accordingly. (commit 8dc873d)

Copilot AI and others added 2 commits October 10, 2025 20:55
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor TOOLS JSON payload into separate file Refactor safe-outputs MCP server tools: Extract to JSON and pre-filter in Go Oct 10, 2025
Copilot AI requested a review from pelikhan October 10, 2025 20:58
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
Copy link
Contributor

@copilot

  • in JavaScript add core.info call to render the tools (JSON. Stringify null 2) after filtering.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Oct 10, 2025

@copilot

...

Added logging to display filtered tools using console.error with JSON.stringify(TOOLS, null, 2). Since this is a standalone MCP server (not running in GitHub Actions context), core.info is not available, so using console.error which writes to stderr and doesn't interfere with the MCP protocol on stdout. (commit 35b07da)

@pelikhan pelikhan closed this Oct 10, 2025
@pelikhan pelikhan deleted the copilot/refactor-tools-json-payload branch October 17, 2025 15:15
Copilot AI mentioned this pull request Feb 16, 2026
21 tasks
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