GraphQL SDL generation and query optimization for SQLModel
Project description
nexusx
Write SQLModel classes. Get a complete API.
Define your entities once in SQLModel, and you get GraphQL, REST, and MCP — no repeated data models.
flowchart LR
sqlmodel["SQLModel"]
sqlmodel --> graphql["GraphQL"]
graphql --> mcp1["MCP"]
sqlmodel --> usecase["UseCaseService"]
usecase --> rest["REST"]
usecase --> mcp2["MCP"]
usecase --> cli["CLI"]
Install
pip install nexusx
pip install nexusx[fastmcp] # with MCP support
Requires Python ≥ 3.10.
Quick Start
Step 1 — Entities + GraphQL
from sqlmodel import SQLModel, Field, Relationship, select
from nexusx import query, mutation, GraphQLHandler
class User(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
posts: list["Post"] = Relationship(back_populates="author")
@query
async def get_users(cls, limit: int = 10) -> list["User"]:
async with get_session() as session:
return (await session.exec(select(cls).limit(limit))).all()
class Post(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
title: str
author_id: int = Field(foreign_key="user.id")
author: User | None = Relationship(back_populates="posts")
handler = GraphQLHandler(base=SQLModel, session_factory=async_session)
Relationships resolve automatically — DataLoader batches queries, one SQL per level:
{ userGetUsers(limit: 5) { name posts { title } } }
Step 2 — Typed REST with DTOs
from nexusx import DefineSubset, ErManager
class UserDTO(DefineSubset):
__subset__ = (User, ("id", "name"))
class PostDTO(DefineSubset):
__subset__ = (Post, ("id", "title", "author_id"))
author: UserDTO | None = None # auto-loaded — field name matches relationship
Resolver = ErManager(base=SQLModel, session_factory=async_session).create_resolver()
dtos = await Resolver().resolve(posts)
DefineSubset is GraphQL field selection in Python — declare which fields you want, get a typed DTO. Relationship fields auto-load when the name matches. Add resolve_* for custom loading, post_* for derived fields.
Step 3 — MCP + REST from business logic
from nexusx import UseCaseService, UseCaseAppConfig, create_use_case_mcp_server, create_use_case_router
class SprintService(UseCaseService):
@query
async def list_sprints(cls) -> list[SprintSummary]:
"""Get all sprints with task counts."""
...
config = UseCaseAppConfig(name="project", services=[SprintService])
# MCP for AI agents
mcp = create_use_case_mcp_server(apps=[config])
mcp.run()
# REST for frontend
app.include_router(create_use_case_router(config))
Same service class, two protocols. Methods can internally use Resolver().resolve(dtos) — the modes compose.
How It Compares
| nexusx | Strawberry | FastAPI + SQLModel | FastMCP | |
|---|---|---|---|---|
| GraphQL auto-gen | ✓ | ✓ | — | — |
| REST + OpenAPI | ✓ | — | ✓ (manual) | — |
| MCP | ✓ | — | — | ✓ |
| N+1 prevention | ✓ DataLoader | manual | — | — |
| Relationship auto-loading | ✓ implicit | manual | — | — |
Demos
git clone https://github.com/allmonday/nexusx.git && cd nexusx && bash start_all.sh
| Port | Mode |
|---|---|
| 8000 | GraphQL playground |
| 8001 | Core API (REST + DTOs) |
| 8005 | Paginated GraphQL |
| 8006 | UseCase MCP (4-layer) |
| 8007 | UseCase FastAPI (REST) |
| 8008 | Voyager visualization |
AI Agent Skill
A 4-phase skill guides AI coding agents: clarify requirements → build POC → add queries → productize.
ln -s $(pwd)/skill ~/.claude/skills/nexusx-4phase
Development
./scripts/check-ci.sh # lint + type-check + tests
uv run pytest # tests only
uv run ruff check src/ tests/ # lint only
uv run mypy src/ # type-check only
Documentation
- API docs — per-mode guides for GraphQL, Core API, and UseCase
- Clean Architecture comparison
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nexusx-2.10.1.tar.gz.
File metadata
- Download URL: nexusx-2.10.1.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27bc7082ccfb6d86ca101929800997ca83755a43c2c1f460cb7dd0783ad339fd
|
|
| MD5 |
591264e6ec671ce2190eefbb4a439b45
|
|
| BLAKE2b-256 |
9f1090670b0b13dd6b35bb1740b290a743dbc4c4fc528c957ec53d537d1d8d3f
|
File details
Details for the file nexusx-2.10.1-py3-none-any.whl.
File metadata
- Download URL: nexusx-2.10.1-py3-none-any.whl
- Upload date:
- Size: 685.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45f900be6c4daa30eca04530f9d235fb37a71c9f89fa2e0fc86e3575af818deb
|
|
| MD5 |
1999a5c78e03afe4d956a8647ba08920
|
|
| BLAKE2b-256 |
e7538207074e270994dd769236ff15cc4bac7533edf3e5c592aa8c31a6e161b6
|