Skip to content

Import multi-platform build from gh-aw release workflow with version support#39

Merged
pelikhan merged 4 commits intomainfrom
copilot/import-go-binary-code
Jan 7, 2026
Merged

Import multi-platform build from gh-aw release workflow with version support#39
pelikhan merged 4 commits intomainfrom
copilot/import-go-binary-code

Conversation

Copy link
Contributor

Copilot AI commented Jan 6, 2026

The release workflow previously built only a single awmg binary. This imports the multi-platform build approach from githubnext/gh-aw to generate binaries for all major platforms with version information.

Changes

  • Added scripts/build-release.sh: Builds binaries for 12 platform/architecture combinations (darwin, linux, freebsd, windows across amd64/arm64/arm/386) with SHA256 checksums
  • Updated .github/workflows/release.md: Replaced make build with the build script, upload all binaries to release instead of single binary
  • Recompiled workflow: Generated updated release.lock.yml
  • Added version.go: Created version variable for build-time version injection
  • Updated CLI: Added --version flag support and version display functionality

Adaptations from gh-aw

  • Binary name: gh-awawmg
  • Output naming: awmg-{platform}{ext}
  • Build path: root directory instead of ./cmd/gh-aw
  • Version injection: Added via -ldflags "-X main.Version=${VERSION}"

Version Support

The build script now injects version information into all binaries during the release process. Users can check their version with awmg --version, which will display the release tag (e.g., awmg version v1.0.0) for release builds or awmg version dev for development builds.

Release artifacts will now include platform-specific binaries with embedded version information and checksums file for verification.

Custom agent used: create-agentic-workflow
Design agentic workflows using GitHub Agentic Workflows (gh-aw) extension with interactive guidance on triggers, tools, and security best practices.

Original prompt

Import the code that builds the go binary for all platforms from githubnext/gh-aw .github/workflows/release.md and import it into the "Build binary" step of release.md in thie project.
Don't forget to recompile.

Custom agent used: create-agentic-workflow
Design agentic workflows using GitHub Agentic Workflows (gh-aw) extension with interactive guidance on triggers, tools, and security best practices.


✨ 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 January 6, 2026 23:31
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] Import code to build Go binary for all platforms Import multi-platform build from gh-aw release workflow Jan 6, 2026
Copilot AI requested a review from pelikhan January 6, 2026 23:38
@pelikhan
Copy link
Collaborator

pelikhan commented Jan 6, 2026

@copilot add version variable support in version.go, update release scripts to set it.

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

Copilot AI commented Jan 6, 2026

@copilot add version variable support in version.go, update release scripts to set it.

Added version support in commit 30d0557:

  • Created version.go with Version variable (default: "dev")
  • Updated scripts/build-release.sh to inject version via -ldflags "-X main.Version=${VERSION}"
  • Added SetVersion() function to set version at runtime
  • Added --version flag support to CLI

The release binaries will now include the version tag (e.g., awmg version v1.0.0).

Copilot AI changed the title Import multi-platform build from gh-aw release workflow Import multi-platform build from gh-aw release workflow with version support Jan 6, 2026
@pelikhan pelikhan marked this pull request as ready for review January 7, 2026 00:04
@pelikhan pelikhan merged commit 886e4aa into main Jan 7, 2026
@pelikhan pelikhan deleted the copilot/import-go-binary-code branch January 7, 2026 00:05
lpcox pushed a commit that referenced this pull request Jan 8, 2026
lpcox added a commit that referenced this pull request Feb 11, 2026
…tories (#889)

Nightly documentation reconciliation identified critical discrepancies
between documented and actual default values, plus incomplete internal
directory listings.

## Changes

### Critical: Payload Size Threshold Default
Updated README.md (3 locations) to reflect actual implementation default
of **10240 bytes (10KB)** instead of incorrectly documented 1024 bytes:
- CLI flag description (line 206)
- Flags usage table (line 281)  
- Environment variables table (line 319)

Implementation sources:
- `internal/cmd/flags_logging.go:14` - `defaultPayloadSizeThreshold =
10240`
- `internal/config/config_payload.go:11` - `DefaultPayloadSizeThreshold
= 10240`

### Minor: Complete Internal Directory Listings
Added missing internal packages to project structure documentation:

**CONTRIBUTING.md**: Added 9 missing directories (auth, difc, envutil,
middleware, sys, testutil, version, tty, timeutil) to both tree diagram
and Key Directories section

**AGENTS.md**: Added 7 missing directories (difc, envutil, middleware,
sys, testutil, tty, version) to project structure list

All 16 internal directories now documented in alphabetical order:
`auth`, `cmd`, `config`, `difc`, `envutil`, `guard`, `launcher`,
`logger`, `mcp`, `middleware`, `server`, `sys`, `testutil`, `timeutil`,
`tty`, `version`

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `example.com`
> - Triggering command: `/tmp/go-build2370360416/b279/launcher.test
/tmp/go-build2370360416/b279/launcher.test
-test.testlogfile=/tmp/go-build2370360416/b279/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/runtime/cgo
git ache/go/1.25.6/x64/pkg/tool/linu-o --global r it 08.o -d go git
x_amd64/vet
e/REDACTED/work/gh/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/vet
64/src/runtime/c-unsafeptr=false 64/bin/git x_amd64/vet` (dns block)
> - `invalid-host-that-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build2370360416/b264/config.test
/tmp/go-build2370360416/b264/config.test
-test.testlogfile=/tmp/go-build2370360416/b264/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/runtime/cgo
HEAD ache/go/1.25.6/x64/pkg/tool/linu-fmessage-length=0 get --global
rgo/bin/git 06.o -d 1.2.0/auth/auth.go git x_amd64/compile get --global
.12/x64/which x_amd64/compile` (dns block)
> - `nonexistent.local`
> - Triggering command: `/tmp/go-build2370360416/b279/launcher.test
/tmp/go-build2370360416/b279/launcher.test
-test.testlogfile=/tmp/go-build2370360416/b279/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/runtime/cgo
git ache/go/1.25.6/x64/pkg/tool/linu-o --global r it 08.o -d go git
x_amd64/vet
e/REDACTED/work/gh/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/vet
64/src/runtime/c-unsafeptr=false 64/bin/git x_amd64/vet` (dns block)
> - `slow.example.com`
> - Triggering command: `/tmp/go-build2370360416/b279/launcher.test
/tmp/go-build2370360416/b279/launcher.test
-test.testlogfile=/tmp/go-build2370360416/b279/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/runtime/cgo
git ache/go/1.25.6/x64/pkg/tool/linu-o --global r it 08.o -d go git
x_amd64/vet
e/REDACTED/work/gh/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/vet
64/src/runtime/c-unsafeptr=false 64/bin/git x_amd64/vet` (dns block)
> - `this-host-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build2370360416/b288/mcp.test
/tmp/go-build2370360416/b288/mcp.test
-test.testlogfile=/tmp/go-build2370360416/b288/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a
64/src/internal/bisect/bisect.go--64 86_64/as --global abis p/bin/git
ache/go/1.25.6/x/tmp/go-build2370360416/b059/vet.cfg -d ; then \
$GOPATH/bin/golangci-lint run --timeout=5m || echo &#34;��� Warning:
golangci-lint failed
/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/link -wdcAJ1yv
x_amd64/vet rt-size &#39;1280,
7/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/vet` (dns
block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/github/gh-aw-mcpg/settings/copilot/coding_agent)
(admins only)
>
> </details>

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>


----

*This section details on the original issue you should resolve*

<issue_title>📚 Documentation Reconciliation Report - February 11,
2026</issue_title>
<issue_description>## Summary

Found **1 critical** and **2 minor** discrepancies between documentation
and implementation during nightly reconciliation check.

- Workflow Run:
[§21890623217](https://github.com/github/gh-aw-mcpg/actions/runs/21890623217)
- Date: February 11, 2026
- Branch: main

## Critical Issues 🔴

Issues that would cause user confusion or broken workflows if followed:

### 1. Payload Size Threshold Default Value Mismatch

**Location:** README.md, lines 206, 281, 319

**Problem:** Documentation states the default payload size threshold is
`1024` bytes (1KB), but the actual implementation uses `10240` bytes
(10KB).

**Actual Behavior:**
- Code: `internal/cmd/flags_logging.go:14` defines
`defaultPayloadSizeThreshold = 10240`
- Code: `internal/config/config_payload.go:11` defines
`DefaultPayloadSizeThreshold = 10240`
- Tests: `internal/cmd/flags_logging_test.go` confirms default is 10240
bytes

**Impact:** Users expecting the documented 1KB threshold will actually
get a 10KB threshold, which could result in:
- More payloads being stored inline than expected (up to 10KB instead of
1KB)
- Less disk I/O than anticipated
- Different memory usage patterns
- Confusion when testing payload storage behavior

**Suggested Fix:** Update README.md to reflect the actual default:

```markdown
# Line 206
- CLI flag: `--payload-size-threshold (bytes)` (default: 10240)

# Line 281
--payload-size-threshold int   Size threshold (in bytes) for storing payloads to disk. Payloads larger than this are stored, smaller ones returned inline (default 10240)

# Line 319
| `MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD` | Size threshold in bytes for payload storage (sets default for `--payload-size-threshold` flag) | `10240` |
```

**Code Reference:**
- `internal/cmd/flags_logging.go:14`
- `internal/config/config_payload.go:11`
- `internal/cmd/flags_logging_test.go:46`

## Minor Issues 🔵

Small inconsistencies or missing details:

### 1. Internal Directory Structure Incomplete in CONTRIBUTING.md

**Location:** CONTRIBUTING.md, lines 206-233 (Project Structure section)

**Problem:** Documentation lists only 7 internal directories, but 16
actually exist.

**Missing Directories:**
- `internal/difc/` - Data Information Flow Control
- `internal/envutil/` - Environment variable utilities
- `internal/middleware/` - HTTP middleware (jq schema processing)
- `internal/sys/` - System utilities
- `internal/testutil/` - Test utilities and helpers
- `internal/tty/` - Terminal detection utilities
- `internal/version/` - Version management

**Impact:** Developers may be unaware of these internal packages when
working on the codebase, potentially duplicating functionality or
missing useful utilities.

**Suggested Fix:** Update the Project Structure section to include all
internal directories with brief descriptions.

**Code Reference:** Directory listing shows all 16 directories exist and
contain working code.

### 2. Internal Directory Structure Incomplete in AGENTS.md

**Location:** AGENTS.md, lines 12-20 (Project Structure section)

**Problem:** Similar to CONTRIBUTING.md, lists only 9 internal
directories instead of 16.

**Missing Directories:** Same as above (difc, envutil, middleware, sys,
testutil, tty, version)

**Impact:** AI agents working with the codebase may not be aware of all
available internal packages.

**Suggested Fix:** Update the Project Structure section to include all
internal directories.

**Code Reference:** Same directory listing as above.

## Documentation Completeness

### Accurate Sections ✅

The following sections were verified and found to be accurate:

- **Go Version Requirement** - Correctly documented as 1.25.0 (matches
`go.mod`)
- **Make Targets** - All 11 documented targets exist and work correctly:
  - `make build`, `test`, `test-unit`, `test-integration`, `test-all`
  - `make lint`, `coverage`, `install`, `agent-finished`
  - `make format`, `clean`
- **Configuration Fields** - All documented fields match code struct
definitions in `internal/config/`
- **Environment Variables** - Correctly documented and extensively used
(140+ references in code)
- **External Links**:
  - MCP Gateway spec link is valid (returns HTTP 200)
  - GitHub token URL is valid (redirects properly)
- **Feature Documentation**:
  - HTTP transport correctly marked as "fully supported"
- Container field requirement for stdio servers matches validation code
- Command field restriction for JSON stdin format accurately documented
  - Sequential launch flag exists and works as documented
- **CLI Flags** - All documented flags exist and match actual
implementation
- **Docker Configuration Examples** - Format and field names match
actual usage
- **Configuration Validation** - Documented behavior matches
`internal/config/validation*.go`

## Tested Commands

All commands from CONTRIBUTING....

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #886
lpcox added a commit that referenced this pull request Feb 15, 2026
…961)

Implements Priority 2 recommendations from the Go Fan module review for
the gojq middleware, adding timeout protection and comprehensive test
coverage.

## Changes

**Timeout Protection**
- Added `DefaultJqTimeout` constant (5 seconds) to prevent query hangs
- Enhanced `applyJqSchema()` to automatically enforce timeout when
context lacks a deadline
- Preserves existing context deadlines when present
- Improved error handling for timeout, cancellation, and compilation
failures

**Documentation**
- Updated code comments to reference gojq v0.12.18 features (536M
element array limit, improved concurrency, enhanced type error messages)
- Enhanced `init()` function documentation explaining fail-fast behavior
- Added detailed timeout behavior documentation in `applyJqSchema()`

**Test Coverage**
- Added 9 comprehensive timeout-related tests covering:
  - Default timeout application for contexts without deadlines
  - Context deadline preservation
  - Large array processing (10,000 elements)
  - Deeply nested structures (10 levels)
  - Compilation error scenarios
  - Context cancellation behavior

**Code Quality**
- Fixed 4 unused `require` declarations in `internal/sys/sys_test.go`

## Example

```go
// Context without deadline automatically gets 5-second timeout
result, err := applyJqSchema(context.Background(), jsonData)

// Existing deadlines are preserved
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
result, err := applyJqSchema(ctx, jsonData)
```

All middleware tests pass (30+ test cases). The implementation leverages
pre-existing query compilation caching (10-100x speedup) while adding
robust timeout protection.

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `example.com`
> - Triggering command: `/tmp/go-build1592018226/b275/launcher.test
/tmp/go-build1592018226/b275/launcher.test
-test.testlogfile=/tmp/go-build1592018226/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a
64/src/math/exp_net/http/httptrace ache/go/1.25.7/x-lang=go1.25 get
go-sdk/internal/-v ache/Python/3.12-buildid
ache/go/1.25.7/xTaEENvXcKh3a5hEPOj9o/TaEENvXcKh3a5hEPOj9o abis��
64/src/runtime/cgo1.25.7 HEAD x_amd64/vet --global fips140/alias` (dns
block)
> - Triggering command: `/tmp/go-build3921665002/b275/launcher.test
/tmp/go-build3921665002/b275/launcher.test
-test.testlogfile=/tmp/go-build3921665002/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
/opt/hostedtoolcache/go/1.25.7/x64/src/net -I 2018226/b260/config.test
--gdwarf-5 --64 -o 2018226/b260/conHEAD e=/t�� t0 m0s docker-compose`
(dns block)
> - Triggering command: `/tmp/go-build1222286590/b275/launcher.test
/tmp/go-build1222286590/b275/launcher.test
-test.testlogfile=/tmp/go-build1222286590/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true MJ37E2qau -tests
ker/docker-init go HEAD 64/pkg/tool/linux_amd64/compile ortcfg -d
aw-mcpg/internal/testutil/mcptest/config.go
aw-mcpg/internal/testutil/mcptest/driver.go /usr/local/sbin/bash g_.a go
x_amd64/vet bash` (dns block)
> - `invalid-host-that-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build1592018226/b260/config.test
/tmp/go-build1592018226/b260/config.test
-test.testlogfile=/tmp/go-build1592018226/b260/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true sonrpc2/conn.go
sonrpc2/frame.go .12/x64/bin/as ;
s#git --global bin/git 64/pkg/include ortc�� 64/src/runtime/cgo
64/src/crypto/internal/fips140de--gdwarf2 inux.go esnew.go ocknew.go
nix_cgo.go nix_cgo_res.go` (dns block)
> - Triggering command: `/tmp/go-build1856060892/b260/config.test
/tmp/go-build1856060892/b260/config.test
-test.testlogfile=/tmp/go-build1856060892/b260/testlog.txt
-test.paniconexit0 -test.timeout=10m0s rev-�� --abbrev-ref HEAD
cal/bin/git tion_pool.go er.go 64/pkg/tool/linux_amd64/vet base64 -d`
(dns block)
> - `nonexistent.local`
> - Triggering command: `/tmp/go-build1592018226/b275/launcher.test
/tmp/go-build1592018226/b275/launcher.test
-test.testlogfile=/tmp/go-build1592018226/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a
64/src/math/exp_net/http/httptrace ache/go/1.25.7/x-lang=go1.25 get
go-sdk/internal/-v ache/Python/3.12-buildid
ache/go/1.25.7/xTaEENvXcKh3a5hEPOj9o/TaEENvXcKh3a5hEPOj9o abis��
64/src/runtime/cgo1.25.7 HEAD x_amd64/vet --global fips140/alias` (dns
block)
> - Triggering command: `/tmp/go-build3921665002/b275/launcher.test
/tmp/go-build3921665002/b275/launcher.test
-test.testlogfile=/tmp/go-build3921665002/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
/opt/hostedtoolcache/go/1.25.7/x64/src/net -I 2018226/b260/config.test
--gdwarf-5 --64 -o 2018226/b260/conHEAD e=/t�� t0 m0s docker-compose`
(dns block)
> - Triggering command: `/tmp/go-build1222286590/b275/launcher.test
/tmp/go-build1222286590/b275/launcher.test
-test.testlogfile=/tmp/go-build1222286590/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true MJ37E2qau -tests
ker/docker-init go HEAD 64/pkg/tool/linux_amd64/compile ortcfg -d
aw-mcpg/internal/testutil/mcptest/config.go
aw-mcpg/internal/testutil/mcptest/driver.go /usr/local/sbin/bash g_.a go
x_amd64/vet bash` (dns block)
> - `slow.example.com`
> - Triggering command: `/tmp/go-build1592018226/b275/launcher.test
/tmp/go-build1592018226/b275/launcher.test
-test.testlogfile=/tmp/go-build1592018226/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a
64/src/math/exp_net/http/httptrace ache/go/1.25.7/x-lang=go1.25 get
go-sdk/internal/-v ache/Python/3.12-buildid
ache/go/1.25.7/xTaEENvXcKh3a5hEPOj9o/TaEENvXcKh3a5hEPOj9o abis��
64/src/runtime/cgo1.25.7 HEAD x_amd64/vet --global fips140/alias` (dns
block)
> - Triggering command: `/tmp/go-build3921665002/b275/launcher.test
/tmp/go-build3921665002/b275/launcher.test
-test.testlogfile=/tmp/go-build3921665002/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
/opt/hostedtoolcache/go/1.25.7/x64/src/net -I 2018226/b260/config.test
--gdwarf-5 --64 -o 2018226/b260/conHEAD e=/t�� t0 m0s docker-compose`
(dns block)
> - Triggering command: `/tmp/go-build1222286590/b275/launcher.test
/tmp/go-build1222286590/b275/launcher.test
-test.testlogfile=/tmp/go-build1222286590/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true MJ37E2qau -tests
ker/docker-init go HEAD 64/pkg/tool/linux_amd64/compile ortcfg -d
aw-mcpg/internal/testutil/mcptest/config.go
aw-mcpg/internal/testutil/mcptest/driver.go /usr/local/sbin/bash g_.a go
x_amd64/vet bash` (dns block)
> - `this-host-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build1592018226/b284/mcp.test
/tmp/go-build1592018226/b284/mcp.test
-test.testlogfile=/tmp/go-build1592018226/b284/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/runtime/cgo
Vl8znsXtV x_amd64/cgo rt-size &#39;1280,
7/opt/hostedtoolcache/go/1.25.7/x64/pkg/tool/linux_amd64/compile
fips140/check cal/bin/npx x_amd64/cgo ortc�� 0938582/b193/_pk-p
mon/httpcommon.ggithub.com/github/gh-aw-mcpg/internal/logger/sanitize
x_amd64/vet unset --global ache/Python/3.12--version x_amd64/vet` (dns
block)
> - Triggering command: `/tmp/go-build1856060892/b284/mcp.test
/tmp/go-build1856060892/b284/mcp.test
-test.testlogfile=/tmp/go-build1856060892/b284/testlog.txt
-test.paniconexit0 -test.timeout=10m0s rev-�� --abbrev-ref HEAD
ache/go/1.25.7/x64/pkg/tool/linux_amd64/compile
/opt/hostedtoolc/opt/hostedtoolcache/go/1.25.7/x64/pkg/tool/linux_amd64/link
0938582/b194/ ache/go/1.25.7/x/tmp/go-build1856060892/b260/config.test
ache/go/1.25.7/x-importcfg de 1665002/b293/_pk-s HEAD 1665002/b293=&gt;
/guard/context.ggrep /guard/guard.go 64/pkg/tool/linu(create|run) git`
(dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/github/gh-aw-mcpg/settings/copilot/coding_agent)
(admins only)
>
> </details>

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>


----

*This section details on the original issue you should resolve*

<issue_title>[go-fan] Go Module Review: gojq - JSON Query
Processing</issue_title>
<issue_description># 🐹 Go Fan Report: github.com/itchyny/gojq

## Module Overview

**gojq** is a pure Go implementation of jq - the powerful JSON query
language and processor. It provides both a CLI tool and a Go library for
programmatically processing JSON data with jq queries. This module is
critical for the MCP Gateway's middleware layer, enabling sophisticated
JSON transformations and schema generation on MCP tool responses.

- **Version**: v0.12.18 (latest)
- **Repository**: https://github.com/itchyny/gojq
- **Stars**: 3,692 ⭐
- **License**: MIT
- **Last Update**: Jan 31, 2026 (13 days ago - very active!)

## Current Usage in gh-aw-mcpg

Based on GitHub code search, gojq is used in **2 files**:

### Files
- `internal/middleware/jqschema.go` - Main implementation for jq-based
schema generation
- `internal/middleware/jqschema_bench_test.go` - Performance benchmarks

### Key APIs Used
The middleware likely leverages:
- `gojq.Parse()` - Parse jq query strings
- `gojq.Compile()` - Compile queries into executable code  
- `Code.Run()` - Execute compiled queries on JSON data
- Iterator pattern for efficient result processing

### Context
The middleware uses gojq for:
- **JSON Schema Generation**: Transform MCP tool response payloads into
JSON schemas
- **Payload Processing**: Handle large JSON responses from backend MCP
servers
- **Performance**: Active benchmarking indicates optimization focus

## Research Findings

### Recent Updates (v0.12.18 - December 2025)

🎉 **Major improvements in latest release:**

1. **New Functions**
- ✨ `trimstr/1` - Efficient prefix/suffix removal (better than string
slicing)
   - ✨ `toboolean/0` - Clean type conversion

2. **Performance & Scale**
- 🚀 **Array index limit increased to 536,870,912 (2^29 elements)** -
huge improvement!
- 🚀 Stopped numeric normalization for concurrent execution - better
parallel performance
- ✨ Support for binding expressions with binary operators (`1 + 2 as $x
| -$x`)

3. **Bug Fixes**
   - 🐛 Fixed `last/1` to be included in `builtins/0`
   - 🐛 Fixed `--indent 0` to preserve newlines
   - 🐛 Fixed string repetition to emit error when result is too large

### Very Recent Activity (January 2026)
- **Jan 31, 2026**: Fixed type error messages for split() and match()
functions
- **Jan 7, 2026**: Updated copyright year and GitHub Actions
- **Ongoing**: Active maintenance with regular updates

### Best Practices from gojq Documentation

1. **Compile Once, Run Many**: Compile queries once and reuse for
massive performance gains
2. **Iterator Pattern**: Use `Run()` which returns an iterator for
memory-efficient processing
3. **Error Handling**: Check both compilation errors (syntax) and
runtime errors (types, null access)
4. **Custom Functions**: Extend jq with Go functions using
`gojq.WithFunction()`
5. **Variables**: Pass variables to queries for dynamic behavior
6. **Memory Management**: Be mindful of large arrays (now supports up to
536M elements!)

## Improvement Opportunities

### 🏃 Quick Wins (High Impact, Low Effort)

#### 1. Leverage New v0.12.18 Functions
**Impact**: Medium | **Effort**: Low

- Use `trimstr/1` instead of manual string slicing for prefix/suffix
removal
- Use `toboolean/0` instead of custom type conversion logic
- **Benefit**: Simpler, more readable jq queries with better performance

**Example**:
``````jq
# Before
.[1:] | if . == "true" then true else false end

# After (with v0.12.18)
trimstr("x") | toboolean
``````

#### 2. Utilize Increased Array Index Limit
**Impact**: High | **Effort**: Low

v0.12.18 dramatically increased the array index limit to **536,870,912
elements (2^29)**:
- Review any artificial limits or pagination in payload processing
- Large MCP tool responses can now be handled directly without chunking
- **Benefit**: Simpler code, better performance for large datasets

#### 3. Improve Error Messages  
**Impact**: Medium | **Effort**: Low

Recent fixes improved type error messages for `split()` and `match()`:
- Ensure error handling captures and logs these enhanced messages
- Add context about which MCP server/tool caused the error
- **Benefit**: Faster debugging and troubleshooting

### ✨ Feature Opportunities (High Impact, Medium/High Effort)

#### 1. Query Compilation Caching 🔥
**Impact**: High | **Effort**: Medium

**Problem**: If jq queries are recompiled on every request, it wastes
significant CPU.

**Solution**: Implement a compilation cache using `sync.Map`:

``````go
var compiledQueries sync.Map // Thread-safe cache

func getOrCompileQuery(queryStr string) (*gojq.Code, error) {
    // Check cache first
    if cached, ok := compiledQueries.Load(queryStr); ok {
        return cached.(*gojq.Code), nil
    }
    
    // Parse and compile
    query, err := gojq.Parse(queryStr)
    if err != nil {
        return nil, fmt.Errorf("failed to parse j...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #921
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