UseCase API Reference
Define business services with UseCaseService, expose them via the 3.0+ GraphQL MCP (create_use_case_graphql_mcp_server), FastAPI REST (create_use_case_router), JSON-RPC (create_jsonrpc_router), CLI (create_use_case_cli), or a plain GraphQL HTTP endpoint (build_compose_schema + compose_introspect).
UseCaseService
Define business services with query and mutation methods for AI agent integration.
from nexusx.use_case import UseCaseService
from nexusx import query, mutation
class SprintService(UseCaseService):
"""Sprint management service."""
@query
async def list_sprints(cls) -> list[SprintSummary]:
...
@query
async def get_sprint(cls, sprint_id: int) -> SprintSummary | None:
...
@mutation
async def create_sprint(cls, name: str) -> SprintSummary:
...
Warning
Follow these rules when defining UseCase methods:
- Methods must be decorated with @query or @mutation
- Methods must be async with cls as the first parameter
- Methods starting with _ are not auto-discovered
- Docstrings become MCP tool descriptions
Rules
- Methods must be decorated with
@queryor@mutation - Methods must be
asyncwithclsas first parameter - Methods starting with
_are not auto-discovered - Docstrings become MCP tool descriptions
Methods
| Method | Description |
|---|---|
get_tag_name() |
Returns the class name as a tag (e.g., "SprintService") |
UseCaseAppConfig
Organize a group of UseCaseServices into one application configuration.
from nexusx.use_case import UseCaseAppConfig
config = UseCaseAppConfig(
name="project",
services=[SprintService, TaskService],
description="Project management API",
)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
str |
Yes | Application name |
services |
list[type[UseCaseService]] |
Yes | List of UseCaseService subclasses |
description |
str \| None |
No | Application description |
context_extractor |
Callable \| None |
No | MCP context extraction function |
create_use_case_graphql_mcp_server
Create an MCP server for UseCase services with multi-app support and four-layer progressive disclosure. Generates a real GraphQL schema (introspection-compatible, GraphiQL-friendly) from UseCaseService signatures; Layer 3 accepts standard GraphQL query strings.
from nexusx.use_case import create_use_case_graphql_mcp_server, UseCaseAppConfig
mcp = create_use_case_graphql_mcp_server(
apps=[
UseCaseAppConfig(
name="project",
services=[SprintService, TaskService],
description="Project management",
),
],
name="Project UseCase API",
)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
apps |
list[UseCaseAppConfig] |
Yes | Application configuration list |
name |
str |
No | Service name |
Generated MCP Tools
| Tool | Description | Response envelope |
|---|---|---|
list_apps() |
List all available apps | {success, data} |
describe_compose_schema(app_name) |
Compact service+method listing (no args/return types) | {success, data} |
describe_compose_method(app_name, service_name, method_name) |
Args + return type + SDL fragment (transitive closure of return type) | {success, data} |
compose_query(app_name, query) |
Execute GraphQL query string | {data, errors} (GraphQL standard) |
Schema structure (fixed three layers)
type Query {
SprintService: SprintServiceQuery!
TaskService: TaskServiceQuery!
}
type SprintServiceQuery {
list_sprints: [SprintSummary!]!
get_sprint(sprint_id: Int!): SprintSummary
}
type Mutation { # only when @mutation methods exist
SprintService: SprintServiceMutation!
}
Layer 3 execution contract
- Accepts standard GraphQL query strings (e.g.
{ SprintService { list_sprints { id title owner { name } } } }) - Field projection: only requested fields are returned (via
subset.build_subset_model) - Rejects introspection (
__schema/__type/__typename) — use Layers 1/2 for schema discovery. This keeps MCP responses compact. - Does NOT wrap results in
Resolver()— service methods own Resolver invocation (callResolver().resolve(dtos)inside the method body when needed) - Concurrent
@querymethods viaasyncio.gather; serial@mutationmethods in query order
Migrating from 2.x
The 2.x direct-call MCP entries (create_use_case_mcp_server, create_use_case_flat_server) were removed in 3.0. See docs/migrations/3.0-use-case-graphql.md for the before/after mapping.
build_compose_schema / ComposeSchema / compose_introspect
Direct schema access for non-MCP use cases (e.g. building a GraphQL HTTP endpoint with GraphiQL).
from nexusx import build_compose_schema, compose_introspect, UseCaseAppConfig
app_config = UseCaseAppConfig(name="project", services=[SprintService, TaskService])
schema = build_compose_schema(app_config)
# Three render views over the same registry:
schema.render_sdl() # full SDL string
schema.render_introspection() # graphql __schema payload (GraphiQL-compatible)
schema.render_method_sdl("SprintService", "list_sprints") # single-method SDL fragment
# Services real introspection queries (for GraphiQL HTTP endpoints):
compose_introspect(schema, "{ __schema { types { name } } }")
# → {"data": {"__schema": {...}}, "errors": None}
See demo/use_case/graphql_server.py for a complete FastAPI /graphql endpoint example.
create_use_case_voyager
Create a Voyager visualization ASGI sub-application for exploring UseCase services.
from nexusx.voyager import create_use_case_voyager
voyager = create_use_case_voyager(
apps=[
UseCaseAppConfig(
name="project",
services=[SprintService, TaskService],
),
],
)
REST Endpoints
| Endpoint | Description |
|---|---|
/dot |
DOT format service dependency graph |
/dot-search |
Searchable DOT graph |
/er-diagram |
Mermaid ER diagram |
/source |
Source code information |
FromContext
Mark parameters for injection from MCP context.
from typing import Annotated
from nexusx.use_case import FromContext
class SprintService(UseCaseService):
@query
async def list_sprints(cls, tenant_id: Annotated[int, FromContext()]) -> list[SprintSummary]:
...
build_dto_select
Build a SELECT statement for querying DTO fields from the SQL database.
from nexusx import build_dto_select
stmt = build_dto_select(SprintSummary)
stmt = build_dto_select(SprintSummary, where=Sprint.id == sprint_id)
Tip
When ORM relationships use lazy="noload" (the recommended pattern with ErManager + Resolver), this function provides minimal benefit since the only pruning is on scalar columns. You can achieve the same result with select(Entity) and DTO.model_validate(entity). Use this function when the DTO selects a small subset of scalar columns from a wide table.