Skip to content

Commit b01a6be

Browse files
authored
Fix Context annotation for FastMCP (#63)
* Register resources after fixing context annotation * docs: record 0.4.1 release
1 parent 16893c1 commit b01a6be

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.4.1] - 2025-06-15
11+
12+
### Fixed
13+
- Ensure autogenerated SQLAlchemy resource functions set the `ctx` annotation
14+
to `EnrichContext` before registration so FastMCP recognizes it as a class
15+
1016
## [0.4.0] - 2025-06-12
1117

1218
### Added

src/enrichmcp/sqlalchemy/auto.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def _register_default_resources(
4040
list_description = f"List {sa_model.__name__} records"
4141
get_description = f"Get a single {sa_model.__name__} by ID"
4242

43-
@app.resource(name=list_name, description=list_description)
4443
async def list_resource(
4544
ctx: EnrichContext, page: int = 1, page_size: int = 20
4645
) -> PageResult[enrich_model]: # type: ignore[name-defined]
@@ -60,14 +59,23 @@ async def list_resource(
6059
has_next=has_next,
6160
)
6261

63-
@app.resource(name=get_name, description=get_description)
62+
# Ensure ctx annotation is an actual class for FastMCP before decorating
63+
list_resource.__annotations__["ctx"] = EnrichContext
64+
65+
list_resource = app.resource(name=list_name, description=list_description)(list_resource)
66+
6467
async def get_resource(ctx: EnrichContext, **kwargs: int) -> enrich_model | None: # type: ignore[name-defined]
6568
entity_id = kwargs[param_name]
6669
session_factory = ctx.request_context.lifespan_context[session_key]
6770
async with session_factory() as session:
6871
obj = await session.get(sa_model, entity_id)
6972
return _sa_to_enrich(obj, enrich_model) if obj else None
7073

74+
# Ensure ctx annotation is an actual class for FastMCP before decorating
75+
get_resource.__annotations__["ctx"] = EnrichContext
76+
77+
get_resource = app.resource(name=get_name, description=get_description)(get_resource)
78+
7179

7280
def _register_relationship_resolvers(
7381
app: EnrichMCP,
@@ -110,6 +118,7 @@ async def func(ctx: EnrichContext, **kwargs: int) -> list[Any]:
110118
return func
111119

112120
resolver = _create_list_resolver()
121+
resolver.__annotations__["ctx"] = EnrichContext
113122
else:
114123

115124
def _create_single_resolver(
@@ -132,6 +141,7 @@ async def func(ctx: EnrichContext, **kwargs: int) -> Any | None:
132141
return func
133142

134143
resolver = _create_single_resolver()
144+
resolver.__annotations__["ctx"] = EnrichContext
135145

136146
resolver.__name__ = f"get_{sa_model.__name__.lower()}_{field_name}"
137147
resolver.__doc__ = description

0 commit comments

Comments
 (0)