9 releases
Uses new Rust 2024
| new 0.3.3 | Feb 24, 2026 |
|---|---|
| 0.3.2 | Feb 11, 2026 |
| 0.2.0 | Feb 3, 2026 |
| 0.1.3 | Feb 3, 2026 |
| 0.1.2 | Jan 19, 2026 |
#2584 in Parser implementations
Used in 3 crates
1.5MB
35K
SLoC
jpx-engine
Protocol-agnostic JMESPath query engine with 400+ functions.
This crate provides the core "brain" of jpx - everything you can do with JMESPath
beyond basic compile and evaluate. It's designed to be transport-agnostic, allowing
the CLI (jpx), MCP server (jpx-mcp), or any future REST/gRPC adapters to be
thin wrappers over this engine.
Features
| Category | Description |
|---|---|
| Evaluation | Single, batch, and string-based evaluation with validation |
| Introspection | List functions, search by keyword, describe, find similar |
| Discovery | Cross-server tool discovery with BM25 search indexing |
| Query Store | Named queries for session-scoped reuse |
| Configuration | Declarative jpx.toml config with layered discovery and merge |
| JSON Utilities | Format, diff, patch, merge, stats, paths, keys |
| Arrow | Apache Arrow conversion (optional, via arrow feature) |
Cargo Features
arrow- Enables Apache Arrow support for columnar data conversion. This adds thearrowmodule with functions to convert between Arrow RecordBatches and JSON Values. Used by the CLI for Parquet I/O.let-expr- Enablesletexpression support (variable bindings in JMESPath expressions). Forwarded from jpx-core. Enabled by default.schema- DerivesJsonSchemaon discovery types for JSON Schema generation. Used by the MCP server for tool schemas.
Quick Start
use jpx_engine::JpxEngine;
use serde_json::json;
let engine = JpxEngine::new();
// Evaluate a JMESPath expression
let result = engine.evaluate("users[*].name", &json!({
"users": [{"name": "alice"}, {"name": "bob"}]
})).unwrap();
assert_eq!(result, json!(["alice", "bob"]));
Evaluation
The engine supports multiple evaluation modes:
use jpx_engine::JpxEngine;
use serde_json::json;
let engine = JpxEngine::new();
// From parsed JSON
let data = json!({"items": [1, 2, 3]});
let result = engine.evaluate("length(items)", &data).unwrap();
assert_eq!(result, json!(3));
// From JSON string
let result = engine.evaluate_str("length(@)", r#"[1, 2, 3]"#).unwrap();
assert_eq!(result, json!(3));
// Batch evaluation (multiple expressions, same input)
let exprs = vec!["a".to_string(), "b".to_string()];
let batch = engine.batch_evaluate(&exprs, &json!({"a": 1, "b": 2}));
assert_eq!(batch.results[0].result, Some(json!(1)));
// Validation without evaluation
let valid = engine.validate("users[*].name");
assert!(valid.valid);
Function Introspection
Discover and explore the 400+ available functions:
use jpx_engine::JpxEngine;
let engine = JpxEngine::new();
// List all categories
let categories = engine.categories();
assert!(categories.contains(&"String".to_string()));
// List functions in a category
let string_funcs = engine.functions(Some("String"));
assert!(string_funcs.iter().any(|f| f.name == "upper"));
// Search by keyword (fuzzy matching, synonyms)
let results = engine.search_functions("upper", 5);
assert!(results.iter().any(|r| r.function.name == "upper"));
// Get detailed function info
let info = engine.describe_function("upper").unwrap();
assert_eq!(info.category, "String");
// Find similar functions
let similar = engine.similar_functions("upper").unwrap();
assert!(!similar.same_category.is_empty());
JSON Utilities
Beyond JMESPath evaluation, the engine provides JSON manipulation tools:
use jpx_engine::JpxEngine;
let engine = JpxEngine::new();
// Pretty-print JSON
let formatted = engine.format_json(r#"{"a":1}"#, 2).unwrap();
assert!(formatted.contains('\n'));
// Generate JSON Patch (RFC 6902)
let patch = engine.diff(r#"{"a": 1}"#, r#"{"a": 2}"#).unwrap();
// Apply JSON Patch
let result = engine.patch(
r#"{"a": 1}"#,
r#"[{"op": "replace", "path": "/a", "value": 2}]"#
).unwrap();
// Apply JSON Merge Patch (RFC 7396)
let merged = engine.merge(
r#"{"a": 1, "b": 2}"#,
r#"{"b": 3, "c": 4}"#
).unwrap();
// Analyze JSON structure
let stats = engine.stats(r#"[1, 2, 3]"#).unwrap();
assert_eq!(stats.root_type, "array");
Query Store
Store and reuse named queries within a session:
use jpx_engine::JpxEngine;
use serde_json::json;
let engine = JpxEngine::new();
// Define a reusable query
engine.define_query(
"active_users".to_string(),
"users[?active].name".to_string(),
Some("Get names of active users".to_string())
).unwrap();
// Run it by name
let data = json!({"users": [
{"name": "alice", "active": true},
{"name": "bob", "active": false}
]});
let result = engine.run_query("active_users", &data).unwrap();
assert_eq!(result, json!(["alice"]));
// List all stored queries
let queries = engine.list_queries().unwrap();
assert_eq!(queries.len(), 1);
Configuration
Load engine settings from jpx.toml files with layered discovery:
use jpx_engine::{JpxEngine, EngineConfig};
// Discover config from standard locations
// (~/.config/jpx/jpx.toml, ./jpx.toml, $JPX_CONFIG)
let config = EngineConfig::discover().unwrap();
let engine = JpxEngine::from_config(config).unwrap();
// Or use the builder for programmatic configuration
let engine = JpxEngine::builder()
.strict(false)
.disable_category("geo")
.disable_function("env")
.build()
.unwrap();
Tool Discovery
Register and search tools across multiple servers (for MCP integration):
use jpx_engine::{JpxEngine, DiscoverySpec};
use serde_json::json;
let engine = JpxEngine::new();
// Register a server's tools
let spec: DiscoverySpec = serde_json::from_value(json!({
"server": {"name": "my-server", "version": "1.0.0"},
"tools": [
{"name": "create_user", "description": "Create a new user", "tags": ["write"]}
]
})).unwrap();
let result = engine.register_discovery(spec, false).unwrap();
assert!(result.ok);
// Search across registered tools
let tools = engine.query_tools("user", 10).unwrap();
assert!(!tools.is_empty());
Strict Mode
For standard JMESPath compliance without extensions:
use jpx_engine::JpxEngine;
use serde_json::json;
let engine = JpxEngine::strict();
assert!(engine.is_strict());
// Standard functions work
let result = engine.evaluate("length(@)", &json!([1, 2, 3])).unwrap();
assert_eq!(result, json!(3));
// Extension functions are not available for evaluation
// (but introspection still works for documentation purposes)
Architecture
jpx-core (parser, runtime, 400+ functions, registry)
|
jpx-engine (this crate - evaluation, search, discovery, config)
|
+----+----+
| |
jpx jpx-mcp (CLI and MCP transport)
Thread Safety
The engine uses interior mutability (Arc<RwLock<...>>) for the discovery
registry and query store, making it safe to share across threads. The function
registry is immutable after construction.
Dependencies
~1.2–7MB
~136K SLoC