/\_/\
( o.o )
> ^ <
A modular Java 21+ framework for exposing resources as capabilities through multiple protocols
This framework is currently in prototype stage. While it compiles and demonstrates core ideas, features may be incomplete or non-functional. Use for experimentation, research, and development purposes only.
Cheshire is a framework that enables developers to expose various resourcesβdatabases, APIs, and servicesβas unified capabilities accessible through multiple protocols including REST, MCP (Model Context Protocol), and more.
The framework features a powerful three-stage pipeline architecture, DSL-based query templates, and federated query processing capabilities, making it ideal for building modern data-driven applications and LLM-powered agents.
"We're all mad here." β The Cheshire Cat
Like its namesake, Cheshire appears wherever you need it, providing a consistent interface to your resources regardless of how they're accessed.
- π Multi-Protocol Support - REST API, MCP stdio, MCP streamable HTTP
- π― Capability-Driven - Resources exposed as business-aligned capabilities
- π Three-Stage Pipelines - PreProcessor β Executor β PostProcessor
- ποΈ DSL Query Templates - JSON-based SQL generation with parameter binding
- π§ Modular Architecture - SPI-based extensibility for custom implementations
- π‘οΈ Type Safe - Leverages Java 21's modern features (records, sealed interfaces, pattern matching)
- β‘ High Performance - Virtual Thread support, lock-free metrics, structured concurrency
- π§© Extensible - Plugin architecture via ServiceLoader for query engines and source providers
- π§ͺ Well Tested - Comprehensive test coverage with reference implementations
- π Comprehensively Documented - 80+ classes with production-ready Javadoc
- Java 21+ (with preview features enabled)
- Maven 3.8+
Add the Cheshire BOM to your pom.xml:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.cheshire</groupId>
<artifactId>cheshire-bom</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>Then add the modules you need:
<dependencies>
<!-- Core framework -->
<dependency>
<groupId>io.cheshire</groupId>
<artifactId>cheshire-core</artifactId>
</dependency>
<!-- Runtime container -->
<dependency>
<groupId>io.cheshire</groupId>
<artifactId>cheshire-runtime</artifactId>
</dependency>
<!-- JDBC Query Engine -->
<dependency>
<groupId>io.cheshire</groupId>
<artifactId>cheshire-query-engine-jdbc</artifactId>
</dependency>
<!-- JDBC Source Provider -->
<dependency>
<groupId>io.cheshire</groupId>
<artifactId>cheshire-source-provider-jdbc</artifactId>
</dependency>
<!-- Server implementations (Jetty + Stdio) -->
<dependency>
<groupId>io.cheshire</groupId>
<artifactId>cheshire-server</artifactId>
</dependency>
</dependencies>Create a simple blog application with multi-protocol support:
package io.blog;
import io.cheshire.core.CheshireBootstrap;
import io.cheshire.core.CheshireSession;
import io.cheshire.runtime.CheshireRuntime;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BlogApp {
public static void main(String[] args) {
log.info("Starting Blog Application...");
// Select configuration based on command-line argument
String configFileName = selectConfigFromArgs(args);
System.setProperty("cheshire.config", configFileName);
try {
// 1. Bootstrap the framework
CheshireSession session = CheshireBootstrap
.fromClasspath("config")
.build();
// 2. Create and start the runtime
CheshireRuntime runtime = CheshireRuntime
.expose(session)
.start();
// 3. Await termination
runtime.awaitTermination();
} catch (Exception e) {
log.error("Fatal startup error", e);
System.exit(1);
}
}
private static String selectConfigFromArgs(String[] args) {
// Configuration is now specified via --config flag
// Handled by PicoCLI command-line parser
// Default: blog-rest.yaml
// For advanced usage, use PicoCLI @CommandLine.Option annotations:
// @Option(names = {"-c", "--config"}, defaultValue = "blog-rest.yaml")
// private String configFile;
return "blog-rest.yaml"; // Default if no --config provided
}
}Run with different protocols:
# REST API on http://localhost:9000/api/v1/blog
java -jar blog-app.jar --config blog-rest.yaml
# MCP via stdio (for LLM agents and Claude Desktop)
java -jar blog-app.jar --config blog-mcp-stdio.yaml \
--log-file /tmp/blog-mcp-stdio.log \
--redirect-stderr
# MCP via HTTP on http://localhost:9000/mcp/v1
java -jar blog-app.jar --config blog-mcp-streamable-http.yamlSee the complete blog-app example for full source code, comprehensive documentation, and testing guides.
- User Guide - Getting started and common use cases
- Pipeline Configuration Guide - Complete guide for configuring pipelines with DSL
- Developer Guide - Extending the framework
- SQL Template DSL Reference - Complete DSL_QUERY specification
- DSL-QUERY - Domain-neutral query template specification
- DSL Resolution - How DSL templates are resolved
- Jetty Configuration - HTTP server configuration
- MCP Integration - Model Context Protocol setup
- Security - Authentication and authorization
- TODOs - Research topics and architectural patterns under investigation
- Performance optimizations (Bloom filters, off-heap streaming, probabilistic data structures)
- Security patterns (RBAC/ABAC with Cedar Policy)
- Query federation (Apache Calcite integration)
- Reactive patterns (Project Reactor, context propagation)
- Extensibility (SPI extensions, runtime compilation)
- Architecture Overview - Visual architecture diagram
Cheshire follows a modular, layered architecture with clear separation of concerns:
The framework consists of seven distinct layers, each with well-defined responsibilities:
- Transport Layer - Network I/O (Jetty HTTP/WebSocket, stdio, TCP)
- Protocol Layer - Multi-protocol support (REST, MCP, WebSocket, GraphQL)
- Server Infrastructure - Protocol adapters, dispatchers, server handles (Virtual Threads)
- Cheshire Core - Session management, capability registry, orchestration
- Three-Stage Pipeline - PreProcessor β Executor β PostProcessor
- Query Engines & Source Providers - JDBC engine, Calcite integration, data source abstraction
- External Resources - Databases, APIs, vector stores, data lakes
Request Flow (Top β Bottom, Red):
- External Request β RequestEnvelope β SessionTask β MaterializedInput β SqlQuery β SQL/API Calls
Response Flow (Bottom β Top, Green):
- Data Rows β MapQueryResult β MaterializedOutput β TaskResult β ResponseEntity β Responses
Business-aligned, self-contained domains that federate data sources and expose operations. Each capability defines:
- Actions - Invocable operations (exposed as MCP tools or REST endpoints)
- Pipelines - Three-stage processing flow for each action
- Exposure - Protocol configuration (REST, MCP stdio, MCP HTTP)
- Transport - Network configuration (port, host, threading)
Every action is processed through three stages:
- PreProcessor - Input validation and transformation
- Executor - Core business logic (query execution, API calls)
- PostProcessor - Output transformation and enrichment
JSON-based query templates that generate SQL dynamically:
{
"operation": "SELECT",
"source": {"table": "articles", "alias": "a"},
"projection": [
{"field": "a.id"},
{"field": "a.title"},
{"field": "a.content"}
],
"filters": {
"conditions": [
{"field": "a.id", "op": "=", "param": "articleId"}
]
}
}See SQL_TEMPLATE_DSL_REFERENCE.md for complete documentation.
| Module | Description |
|---|---|
| cheshire-bom | Bill of Materials for dependency management |
| cheshire-core | Core framework (Session, Managers, Capabilities, Pipelines) |
| cheshire-runtime | Operational container with structured concurrency |
| cheshire-common | Shared utilities, exceptions, and configuration |
| Module | Description |
|---|---|
| cheshire-pipeline-spi | Pipeline processor interfaces (PreProcessor, Executor, PostProcessor) |
| cheshire-query-engine-spi | Query engine abstraction and factory |
| cheshire-source-provider-spi | Source provider abstraction and factory |
| Module | Description |
|---|---|
| cheshire-query-engine-jdbc | Direct JDBC query execution with DSL_QUERY support |
| cheshire-query-engine-calcite | Apache Calcite integration for federated queries |
| cheshire-source-provider-jdbc | JDBC data source provider with connection management |
| cheshire-server | Server implementations (Jetty HTTP, stdio) |
| Module | Description |
|---|---|
| cheshire-security | Authentication, authorization, and security utilities |
| cheshire-test-common | Common testing utilities and fixtures |
Expose databases to LLM agents via MCP protocol:
# config/blog-mcp-stdio.yaml
capabilities:
blogmcpstdio:
name: blog-mcp-stdio
description: "Blog database via MCP stdio"
exposure:
type: MCP_STDIO
binding: MCP_STDIO
actions-specification-file: blog-actions.yaml
pipelines-definition-file: blog-pipelines.yamlExposed Actions (automatically discovered by LLM agents):
create_author,update_author,delete_author,get_author,list_authorscreate_article,update_article,delete_article,get_article,list_articlessearch_articles,list_published_articlescreate_comment,delete_comment,list_comments_by_article
Expose the same capability through multiple protocols:
// Same actions accessible via:
// 1. REST API: http://localhost:9000/api/v1/blog
// 2. MCP HTTP: http://localhost:9000/mcp/v1
// 3. MCP stdio: java -jar app.jar --config blog-mcp-stdio.yamlUse DSL templates for type-safe, injectable SQL queries:
{
"operation": "SELECT",
"source": {"table": "articles", "alias": "a"},
"joins": [
{
"type": "LEFT",
"table": "authors",
"alias": "au",
"on": [{"left": "a.author_id", "op": "=", "right": "au.id"}]
}
],
"filters": {
"op": "AND",
"conditions": [
{"field": "a.status", "op": "=", "param": "status"},
{"field": "a.published_at", "op": ">=", "param": "fromDate"}
]
}
}Parameters are safely bound at runtime:
Map<String, Object> params = Map.of(
"status", "published",
"fromDate", LocalDateTime.now().minusDays(7)
);Implement custom processing logic:
@Slf4j
public class CustomInputProcessor implements PreProcessor {
@Override
public MaterializedInput process(MaterializedInput input) {
// Validate, transform, enrich input
var transformed = validateAndTransform(input);
log.debug("Input processed: {}", transformed);
return transformed;
}
}
@Slf4j
public class CustomExecutor implements Executor {
@Override
public MaterializedOutput execute(MaterializedInput input, SessionTask task) {
// Execute business logic
var result = executeBusinessLogic(input, task);
return MaterializedOutput.of(result);
}
}- Java 25 (with preview features enabled)
- No Maven installation required! - Project includes Maven wrapper
# Clone the repository
git clone https://github.com/cheshire-framework/cheshire-framework.git
cd cheshire-framework/cheshire
# Build using Maven wrapper (no Maven installation needed!)
./mvnw clean install
# Or on Windows
mvnw.cmd clean install# Full build with tests
./mvnw clean install
# Build without tests (faster)
./mvnw clean install -DskipTests
# Build with test coverage
./mvnw clean install jacoco:report
# Build individual module
cd cheshire-core
../mvnw clean install
# Clean all build artifacts
./mvnw clean
# Run tests only
./mvnw test
# Run integration tests
./mvnw verifyIf you have Maven 3.8+ installed, you can use it directly:
mvn clean installThe project includes Maven Wrapper (mvnw) which:
- β Downloads correct Maven version (3.9.6) automatically
- β Ensures consistent builds across environments
- β No need to install Maven manually
- β Works on Linux, macOS, and Windows
The blog application is a complete reference implementation demonstrating all Cheshire features:
Features:
- β Full CRUD operations (Authors, Articles, Comments)
- β Three protocol exposures (REST, MCP stdio, MCP HTTP)
- β 15+ operations with comprehensive validation
- β DSL-based query templates
- β PostgreSQL with Docker or H2 in-memory database
- β Complete testing guide with curl examples
- β Claude Desktop integration for AI agents
- β OpenAPI and Postman collections
# Navigate to blog-app
cd ../cheshire-blog-app
# Build the application
mvn clean package
# Run with REST API (default)
java -jar target/blog-app-1.0-SNAPSHOT.jar --config blog-rest.yaml
# Access at: http://localhost:9000/api/v1/blog
# Run with MCP stdio (for Claude Desktop)
java -jar target/blog-app-1.0-SNAPSHOT.jar \
--config blog-mcp-stdio.yaml \
--log-file /tmp/blog-mcp-stdio.log \
--redirect-stderr
# Run with MCP HTTP (with streaming)
java -jar target/blog-app-1.0-SNAPSHOT.jar --config blog-mcp-streamable-http.yaml
# Access at: http://localhost:9000/mcp/v1# REST API
mvn exec:java -Dexec.mainClass="io.blog.BlogApp" \
-Dexec.args="--config blog-rest.yaml"
# MCP stdio
mvn exec:java -Dexec.mainClass="io.blog.BlogApp" \
-Dexec.args="--config blog-mcp-stdio.yaml --log-file /tmp/blog-mcp-stdio.log --redirect-stderr"
# MCP HTTP
mvn exec:java -Dexec.mainClass="io.blog.BlogApp" \
-Dexec.args="--config blog-mcp-streamable-http.yaml"# Option 1: Use H2 in-memory (default - no setup needed)
# Pre-populated with test data (8 authors, 9 articles, 10 comments)
# Option 2: Use PostgreSQL with Docker
cd infra
docker-compose up -d
cd ..
java -jar target/blog-app-1.0-SNAPSHOT.jar --config blog-rest.yaml
# Option 3: Generate custom test data
cd infra/postgres
source venv/bin/activate
python populate_db.py --generate --authors 100 --articles 500 --comments 2000
cd ../..# Test REST API
curl "http://localhost:9000/api/v1/blog/list_authors?page=1&limit=10"
# Create author
curl "http://localhost:9000/api/v1/blog/create_author?username=demo_user&email=demo@example.com"
# Get statistics
curl "http://localhost:9000/api/v1/blog/stats_overview"See cheshire-blog-app/TESTING.md for comprehensive testing guide.
For guidance on issue types, commit message conventions, branch naming, and spike/task templates, please refer to our Development Taxonomy.
This includes:
- GitHub issue prefixes (
TASK:,BUG:,SPIKE:etc.) - Conventional commit prefixes (
feat:,fix:,docs:,refactor:etc.) - Branch naming conventions
- Guidance on optional vs automatic issue linking in commits
βββ cheshire-prototype/ # Core framework
β βββ cheshire-bom/ # Dependency management
β βββ cheshire-core/ # Core framework (Session, Managers, Capabilities)
β βββ cheshire-runtime/ # Runtime container with structured concurrency
β βββ cheshire-pipeline-spi/ # Pipeline processor interfaces
β βββ cheshire-query-engine-spi/ # Query engine interfaces
β βββ cheshire-query-engine-jdbc/ # JDBC query implementation
β βββ cheshire-query-engine-calcite/ # Calcite integration (federated queries)
β βββ cheshire-source-provider-spi/ # Source provider interfaces
β βββ cheshire-source-provider-jdbc/ # JDBC source implementation
β βββ cheshire-server/ # Server implementations (Jetty, stdio)
β βββ cheshire-common/ # Shared utilities and configuration
β βββ cheshire-security/ # Security features
β βββ docs/ # Framework documentation
β βββ guides/user/ # User guides and tutorials
β βββ guides/developer/ # Developer guides
β βββ reference/ # Reference documentation
β βββ TODOs/ # Exploration topics and research
Cheshire follows Scala-influenced functional Java style:
- Immutability by default - All fields
final, use records - No nulls - Use
Optional<T>everywhere - Declarative - Prefer Streams API over imperative loops
- Expressions over statements - Use switch expressions, ternary operators
- Pure functions - Push side effects to boundaries
See .cursorrules for complete style guide.
# Run all tests
mvn test
# Run specific module tests
cd cheshire-core
mvn test
# Run integration tests
mvn verify
# Run with coverage
mvn clean test jacoco:reportCurrent progress, upcoming features, and bug fixes: GitHub Project Board.
- TBF
- TBF
- TBF
The Blog Application serves as the primary reference implementation, featuring:
- Complete CRUD operations for Authors, Articles, and Comments
- Multi-protocol support (REST, MCP stdio, MCP HTTP)
- Comprehensive testing guide with 1,800+ lines of documentation
- Database setup with PostgreSQL Docker and H2 in-memory options
- Test data generation scripts for performance testing
- Claude Desktop integration examples
- OpenAPI 3.0 and Postman collections
- Production-ready pipeline configurations
See cheshire-blog-app/README.md for complete documentation.
- Documentation: docs/
This project was built using a Human-in-the-Loop AI workflow, leveraging LLMs as a force-multiplier for development velocity
This project is licensed under the PolyForm Noncommercial License 1.0.0.
See the LICENSE file for the full license text.
Created by Halim Chaibi