🐹 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.
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:
-
New Functions
- ✨
trimstr/1 - Efficient prefix/suffix removal (better than string slicing)
- ✨
toboolean/0 - Clean type conversion
-
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)
-
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
- Compile Once, Run Many: Compile queries once and reuse for massive performance gains
- Iterator Pattern: Use
Run() which returns an iterator for memory-efficient processing
- Error Handling: Check both compilation errors (syntax) and runtime errors (types, null access)
- Custom Functions: Extend jq with Go functions using
gojq.WithFunction()
- Variables: Pass variables to queries for dynamic behavior
- 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:
# 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:
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 jq query: %w", err)
}
code, err := gojq.Compile(query)
if err != nil {
return nil, fmt.Errorf("failed to compile jq query: %w", err)
}
// Cache for reuse
compiledQueries.Store(queryStr, code)
return code, nil
}
Benefit: 10-100x performance improvement for repeated queries! Compilation is expensive; caching eliminates this overhead.
2. Custom MCP Functions
Impact: High | Effort: Medium
Add domain-specific jq functions for common MCP operations:
code, err := gojq.Compile(query,
gojq.WithFunction("mcpToolName", 1, 1, func(v interface{}) interface{} {
// Extract tool name from MCP response structure
if m, ok := v.(map[string]interface{}); ok {
if tool, ok := m["tool"].(string); ok {
return tool
}
}
return nil
}),
gojq.WithFunction("mcpServerID", 1, 1, func(v interface{}) interface{} {
// Extract server ID from MCP response metadata
if m, ok := v.(map[string]interface{}); ok {
if meta, ok := m["_meta"].(map[string]interface{}); ok {
return meta["serverId"]
}
}
return nil
}),
gojq.WithFunction("mcpTimestamp", 1, 1, func(v interface{}) interface{} {
// Extract and format timestamp from MCP response
// Return ISO 8601 formatted string
}),
)
Benefit:
- More maintainable jq queries (less complex string manipulation)
- Encapsulate MCP-specific logic in Go (easier to test and refactor)
- Cleaner separation of concerns
3. Streaming for Large Payloads
Impact: High | Effort: High
Use gojq's streaming capabilities for very large MCP tool responses:
// Instead of loading entire payload into memory
dec := json.NewDecoder(largePayloadReader)
iter := code.RunWithContext(ctx, dec)
for {
v, ok := iter.Next()
if !ok {
break
}
if err, ok := v.(error); ok {
return fmt.Errorf("jq processing error: %w", err)
}
// Process each result incrementally
processResult(v)
}
Benefit:
- Lower memory footprint - process payloads larger than available RAM
- Better latency - start processing before entire payload is received
- More scalable for massive MCP tool responses
4. Concurrent Query Execution
Impact: Medium | Effort: Medium
v0.12.18 improved concurrent execution by stopping numeric normalization:
// Process multiple payloads concurrently
var wg sync.WaitGroup
results := make(chan Result, len(payloads))
for _, payload := range payloads {
wg.Add(1)
go func(p Payload) {
defer wg.Done()
code, _ := getOrCompileQuery(schemaQuery) // Uses cache!
iter := code.Run(p.Data)
result := collectResults(iter)
results <- result
}(payload)
}
wg.Wait()
close(results)
Benefit: Faster batch processing of MCP responses, better throughput
📐 Best Practice Alignment
1. Timeout Protection ⏱️
Impact: High | Effort: Low
Problem: Malformed jq queries or large payloads can cause hangs.
Solution: Add context timeouts:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
iter := code.RunWithContext(ctx, input)
for {
v, ok := iter.Next()
if !ok {
break
}
if err, ok := v.(error); ok {
if errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("jq query timed out after 5s: %w", err)
}
return fmt.Errorf("jq query failed: %w", err)
}
// Process v
}
Benefit: Prevent infinite loops, ensure gateway responsiveness
2. Query Validation at Startup 🚀
Impact: High | Effort: Low
Problem: Runtime jq syntax errors are hard to debug.
Solution: Validate all static queries during initialization:
func init() {
staticQueries := []string{
schemaQuery,
metadataQuery,
transformQuery,
}
for _, q := range staticQueries {
if _, err := gojq.Parse(q); err != nil {
log.Fatalf("Invalid jq query at startup: %s\nError: %v", q, err)
}
}
}
Benefit: Fail fast, catch errors before production deployment
3. Error Wrapping 📦
Impact: Medium | Effort: Low
Ensure all gojq errors are properly wrapped with context:
if err, ok := v.(error); ok {
return fmt.Errorf(
"jq query failed on MCP payload (server: %s, tool: %s, query: %s): %w",
serverID, toolName, queryStr, err,
)
}
Benefit: Better debugging with full context in error logs
4. Enhanced Benchmarking 📊
Impact: Medium | Effort: Low
The project already has jqschema_bench_test.go - excellent! Suggested enhancements:
// Benchmark compilation caching impact
func BenchmarkQueryWithCache(b *testing.B) {
for i := 0; i < b.N; i++ {
code, _ := getOrCompileQuery(schemaQuery) // Cached
code.Run(testPayload)
}
}
func BenchmarkQueryWithoutCache(b *testing.B) {
for i := 0; i < b.N; i++ {
query, _ := gojq.Parse(schemaQuery)
code, _ := gojq.Compile(query) // Recompiled every time
code.Run(testPayload)
}
}
// Benchmark large array handling (2^29 elements)
func BenchmarkLargeArrayProcessing(b *testing.B) {
largeArray := make([]int, 1000000) // 1M elements
// ...
}
// Benchmark new v0.12.18 functions
func BenchmarkTrimstrFunction(b *testing.B) {
// ...
}
Benefit: Quantify improvements, identify regressions
🔧 General Improvements
1. Documentation 📚
Impact: Medium | Effort: Low
- Document which jq version/features are being used (mention v0.12.18 features)
- Provide examples of supported jq queries in code comments
- Document any custom functions and their signatures
- Add troubleshooting guide for common jq errors
Example:
// SchemaQuery generates a JSON schema from MCP tool response payloads.
//
// Supported jq features (requires gojq v0.12.18+):
// - trimstr/1: Efficient string prefix/suffix removal
// - toboolean/0: Type conversion to boolean
// - Array index limit: Up to 536,870,912 elements (2^29)
//
// Example query:
// .result | keys[] | {(.): (. | type)}
//
// Common errors:
// - "cannot index X with string": Input is not an object
// - "X cannot be matched against": Regex error in match()
const SchemaQuery = `...`
2. Testing 🧪
Impact: Medium | Effort: Medium
- Test edge cases with very large arrays (up to 2^29 elements)
- Test error scenarios with new enhanced error messages
- Add tests for new
trimstr and toboolean functions
- Test timeout handling and cancellation
- Test concurrent query execution
3. Monitoring 📈
Impact: Medium | Effort: Medium
Add metrics for observability:
// Histogram for query execution time
jqQueryDuration := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "mcp_jq_query_duration_seconds",
Help: "jq query execution duration",
Buckets: prometheus.ExponentialBuckets(0.001, 2, 10),
},
[]string{"query_name", "server_id"},
)
// Counter for cache hits
jqCacheHits := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "mcp_jq_cache_hits_total",
Help: "Number of jq query cache hits",
},
[]string{"query_name"},
)
// Gauge for payload sizes
jqPayloadSize := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "mcp_jq_payload_bytes",
Help: "Size of JSON payloads processed by jq",
Buckets: prometheus.ExponentialBuckets(1024, 4, 8),
},
[]string{"server_id", "tool_name"},
)
Alert examples:
- Query execution > 1 second
- Payload size > 10MB
- Cache hit rate < 80%
- Query timeout errors
4. Version Upgrade Path 🔄
Impact: Low | Effort: Low
- Document dependency on v0.12.18 features (array limit, new functions)
- Watch gojq releases for new features and bug fixes
- Test compatibility with new jq spec versions
- Consider contributing improvements back to gojq (query cache example?)
Recommendations
Priority 1: High Impact, Low Effort ⭐
- ✅ Add timeout protection to prevent hangs from malformed queries
- ✅ Validate queries at startup for fail-fast behavior
- ✅ Leverage new array limit (2^29 elements) - remove artificial pagination
- ✅ Use new trimstr/toboolean functions for cleaner queries
Priority 2: High Impact, Medium Effort 🚀
- ✅ Implement query compilation caching - 10-100x speedup!
- ✅ Add custom MCP functions for cleaner, more maintainable queries
- ✅ Improve error wrapping with server/tool context
Priority 3: High Impact, High Effort 💪
- 🔄 Implement streaming for memory-efficient large payload processing
- 🔄 Add concurrent query execution for batch operations
Priority 4: Maintenance & Quality 📝
- 📝 Enhance documentation with examples and troubleshooting
- 📊 Add monitoring metrics for query performance and cache effectiveness
- 🧪 Expand test coverage for edge cases and new v0.12.18 features
Next Steps
-
Audit Current Implementation: Review internal/middleware/jqschema.go:
- Is query compilation caching already implemented?
- Are there timeout protections?
- How are errors being handled?
- Which jq queries are being used?
-
Benchmark Current Performance: Establish baseline:
- Average query execution time
- Memory usage for typical/large payloads
- Cache hit rates (if caching exists)
-
Implement Quick Wins: Start with Priority 1 items:
- Add timeout protection (context.WithTimeout)
- Validate static queries at startup
- Update queries to use trimstr/toboolean where applicable
-
Plan Feature Improvements: Design Priority 2 items:
- Query compilation cache architecture
- Custom MCP function signatures
- Error handling standards
-
Monitor and Iterate: Track improvements:
- Measure performance gains from caching
- Monitor production metrics (latency, errors, payload sizes)
- Adjust based on real-world usage patterns
Conclusion
gojq v0.12.18 is an excellent, actively maintained module that's perfect for the MCP Gateway's JSON processing needs. The recent updates bring significant improvements:
- 🎉 536M element array limit enables processing of massive MCP tool responses
- 🎉 New built-in functions (
trimstr, toboolean) simplify queries
- 🎉 Concurrent execution improvements enable better performance
- 🎉 Active maintenance with regular bug fixes and enhancements
The highest-impact improvement is implementing query compilation caching - this single change could deliver 10-100x performance improvement for repeated queries. Combined with timeout protection and custom MCP functions, the middleware layer will be significantly more robust and performant.
Module Status: ✅ Highly recommended for continued use with suggested optimizations
Module Summary: Saved to /tmp/gh-aw/cache-memory/gojq-module-summary.md
Repository: https://github.com/itchyny/gojq
Changelog: https://github.com/itchyny/gojq/blob/main/CHANGELOG.md
jq Manual: (stedolan.github.io/redacted)
Last Reviewed: 2026-02-13
Generated by Go Fan 🐹 - Your enthusiastic Go module reviewer!
AI generated by Go Fan
🐹 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.
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 generationinternal/middleware/jqschema_bench_test.go- Performance benchmarksKey APIs Used
The middleware likely leverages:
gojq.Parse()- Parse jq query stringsgojq.Compile()- Compile queries into executable codeCode.Run()- Execute compiled queries on JSON dataContext
The middleware uses gojq for:
Research Findings
Recent Updates (v0.12.18 - December 2025)
🎉 Major improvements in latest release:
New Functions
trimstr/1- Efficient prefix/suffix removal (better than string slicing)toboolean/0- Clean type conversionPerformance & Scale
1 + 2 as $x | -$x)Bug Fixes
last/1to be included inbuiltins/0--indent 0to preserve newlinesVery Recent Activity (January 2026)
Best Practices from gojq Documentation
Run()which returns an iterator for memory-efficient processinggojq.WithFunction()Improvement Opportunities
🏃 Quick Wins (High Impact, Low Effort)
1. Leverage New v0.12.18 Functions
Impact: Medium | Effort: Low
trimstr/1instead of manual string slicing for prefix/suffix removaltoboolean/0instead of custom type conversion logicExample:
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):
3. Improve Error Messages
Impact: Medium | Effort: Low
Recent fixes improved type error messages for
split()andmatch():✨ 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:Benefit: 10-100x performance improvement for repeated queries! Compilation is expensive; caching eliminates this overhead.
2. Custom MCP Functions
Impact: High | Effort: Medium
Add domain-specific jq functions for common MCP operations:
Benefit:
3. Streaming for Large Payloads
Impact: High | Effort: High
Use gojq's streaming capabilities for very large MCP tool responses:
Benefit:
4. Concurrent Query Execution
Impact: Medium | Effort: Medium
v0.12.18 improved concurrent execution by stopping numeric normalization:
Benefit: Faster batch processing of MCP responses, better throughput
📐 Best Practice Alignment
1. Timeout Protection ⏱️
Impact: High | Effort: Low
Problem: Malformed jq queries or large payloads can cause hangs.
Solution: Add context timeouts:
Benefit: Prevent infinite loops, ensure gateway responsiveness
2. Query Validation at Startup 🚀
Impact: High | Effort: Low
Problem: Runtime jq syntax errors are hard to debug.
Solution: Validate all static queries during initialization:
Benefit: Fail fast, catch errors before production deployment
3. Error Wrapping 📦
Impact: Medium | Effort: Low
Ensure all gojq errors are properly wrapped with context:
Benefit: Better debugging with full context in error logs
4. Enhanced Benchmarking 📊
Impact: Medium | Effort: Low
The project already has
jqschema_bench_test.go- excellent! Suggested enhancements:Benefit: Quantify improvements, identify regressions
🔧 General Improvements
1. Documentation 📚
Impact: Medium | Effort: Low
Example:
2. Testing 🧪
Impact: Medium | Effort: Medium
trimstrandtobooleanfunctions3. Monitoring 📈
Impact: Medium | Effort: Medium
Add metrics for observability:
Alert examples:
4. Version Upgrade Path 🔄
Impact: Low | Effort: Low
Recommendations
Priority 1: High Impact, Low Effort ⭐
Priority 2: High Impact, Medium Effort 🚀
Priority 3: High Impact, High Effort 💪
Priority 4: Maintenance & Quality 📝
Next Steps
Audit Current Implementation: Review
internal/middleware/jqschema.go:Benchmark Current Performance: Establish baseline:
Implement Quick Wins: Start with Priority 1 items:
Plan Feature Improvements: Design Priority 2 items:
Monitor and Iterate: Track improvements:
Conclusion
gojq v0.12.18 is an excellent, actively maintained module that's perfect for the MCP Gateway's JSON processing needs. The recent updates bring significant improvements:
trimstr,toboolean) simplify queriesThe highest-impact improvement is implementing query compilation caching - this single change could deliver 10-100x performance improvement for repeated queries. Combined with timeout protection and custom MCP functions, the middleware layer will be significantly more robust and performant.
Module Status: ✅ Highly recommended for continued use with suggested optimizations
Module Summary: Saved to
/tmp/gh-aw/cache-memory/gojq-module-summary.mdRepository: https://github.com/itchyny/gojq
Changelog: https://github.com/itchyny/gojq/blob/main/CHANGELOG.md
jq Manual: (stedolan.github.io/redacted)
Last Reviewed: 2026-02-13
Generated by Go Fan 🐹 - Your enthusiastic Go module reviewer!