Skip to content

Commit 0d99804

Browse files
Adjust input params (#18)
* Adjust input parameters * Add operation logging * Enable customers tool
1 parent 415ca5e commit 0d99804

File tree

13 files changed

+156
-60
lines changed

13 files changed

+156
-60
lines changed

src/saleor_mcp/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
LOGLEVEL = os.environ.get("LOGLEVEL", "INFO").upper()
1010
logging.basicConfig(level=LOGLEVEL)
11+
logging.getLogger("mcp.server.streamable_http").setLevel(logging.WARNING)
1112

1213

1314
def validate_api_url(url, pattern):

src/saleor_mcp/graphql/ListCustomers.graphql

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
query ListCustomers(
22
$first: Int
3+
$after: String
34
$sortBy: UserSortingInput
45
$where: CustomerWhereInput
56
$search: String
67
) {
7-
customers(first: $first, sortBy: $sortBy, where: $where, search: $search) {
8+
customers(
9+
first: $first
10+
after: $after
11+
sortBy: $sortBy
12+
where: $where
13+
search: $search
14+
) {
815
pageInfo {
916
hasNextPage
1017
hasPreviousPage

src/saleor_mcp/main.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
from fastmcp import FastMCP
2+
from fastmcp.server.middleware.timing import DetailedTimingMiddleware
23
from starlette.requests import Request
34
from starlette.responses import FileResponse, JSONResponse
45
from starlette.staticfiles import StaticFiles
56

67
from saleor_mcp.tools import (
78
channels_router,
9+
customers_router,
810
orders_router,
911
products_router,
1012
utils_router,
1113
)
1214

1315
mcp = FastMCP("Saleor MCP Server")
16+
mcp.add_middleware(DetailedTimingMiddleware())
1417
mcp.mount(channels_router)
18+
mcp.mount(customers_router)
1519
mcp.mount(orders_router)
1620
mcp.mount(products_router)
1721
mcp.mount(utils_router)

src/saleor_mcp/saleor_client/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
PromotionSortField,
139139
PromotionTypeEnum,
140140
PromotionUpdateErrorCode,
141+
RefundSettingsErrorCode,
141142
ReportingPeriod,
142143
RewardTypeEnum,
143144
RewardValueTypeEnum,
@@ -454,6 +455,7 @@
454455
PromotionUpdateInput,
455456
PromotionWhereInput,
456457
PublishableChannelListingInput,
458+
RefundSettingsUpdateInput,
457459
ReorderInput,
458460
SaleChannelListingAddInput,
459461
SaleChannelListingInput,
@@ -1026,6 +1028,8 @@
10261028
"PromotionUpdateInput",
10271029
"PromotionWhereInput",
10281030
"PublishableChannelListingInput",
1031+
"RefundSettingsErrorCode",
1032+
"RefundSettingsUpdateInput",
10291033
"ReorderInput",
10301034
"ReportingPeriod",
10311035
"RewardTypeEnum",

src/saleor_mcp/saleor_client/client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,22 @@ async def list_channels(self, **kwargs: Any) -> ListChannels:
7878
async def list_customers(
7979
self,
8080
first: Union[Optional[int], UnsetType] = UNSET,
81+
after: Union[Optional[str], UnsetType] = UNSET,
8182
sortBy: Union[Optional[UserSortingInput], UnsetType] = UNSET,
8283
where: Union[Optional[CustomerWhereInput], UnsetType] = UNSET,
8384
search: Union[Optional[str], UnsetType] = UNSET,
8485
**kwargs: Any
8586
) -> ListCustomers:
8687
query = gql(
8788
"""
88-
query ListCustomers($first: Int, $sortBy: UserSortingInput, $where: CustomerWhereInput, $search: String) {
89-
customers(first: $first, sortBy: $sortBy, where: $where, search: $search) {
89+
query ListCustomers($first: Int, $after: String, $sortBy: UserSortingInput, $where: CustomerWhereInput, $search: String) {
90+
customers(
91+
first: $first
92+
after: $after
93+
sortBy: $sortBy
94+
where: $where
95+
search: $search
96+
) {
9097
pageInfo {
9198
hasNextPage
9299
hasPreviousPage
@@ -139,6 +146,7 @@ async def list_customers(
139146
)
140147
variables: Dict[str, object] = {
141148
"first": first,
149+
"after": after,
142150
"sortBy": sortBy,
143151
"where": where,
144152
"search": search,

src/saleor_mcp/saleor_client/enums.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,17 @@ class AttributeEntityTypeEnum(str, Enum):
17311731
COLLECTION = "COLLECTION"
17321732

17331733

1734+
class ProductTypeKindEnum(str, Enum):
1735+
NORMAL = "NORMAL"
1736+
GIFT_CARD = "GIFT_CARD"
1737+
1738+
1739+
class VariantAttributeScope(str, Enum):
1740+
ALL = "ALL"
1741+
VARIANT_SELECTION = "VARIANT_SELECTION"
1742+
NOT_VARIANT_SELECTION = "NOT_VARIANT_SELECTION"
1743+
1744+
17341745
class AttributeTypeEnum(str, Enum):
17351746
PRODUCT_TYPE = "PRODUCT_TYPE"
17361747
PAGE_TYPE = "PAGE_TYPE"
@@ -1778,17 +1789,6 @@ class AttributeChoicesSortField(str, Enum):
17781789
SLUG = "SLUG"
17791790

17801791

1781-
class ProductTypeKindEnum(str, Enum):
1782-
NORMAL = "NORMAL"
1783-
GIFT_CARD = "GIFT_CARD"
1784-
1785-
1786-
class VariantAttributeScope(str, Enum):
1787-
ALL = "ALL"
1788-
VARIANT_SELECTION = "VARIANT_SELECTION"
1789-
NOT_VARIANT_SELECTION = "NOT_VARIANT_SELECTION"
1790-
1791-
17921792
class StockAvailability(str, Enum):
17931793
IN_STOCK = "IN_STOCK"
17941794
OUT_OF_STOCK = "OUT_OF_STOCK"
@@ -2541,6 +2541,12 @@ class GiftCardSettingsErrorCode(str, Enum):
25412541
GRAPHQL_ERROR = "GRAPHQL_ERROR"
25422542

25432543

2544+
class RefundSettingsErrorCode(str, Enum):
2545+
INVALID = "INVALID"
2546+
REQUIRED = "REQUIRED"
2547+
GRAPHQL_ERROR = "GRAPHQL_ERROR"
2548+
2549+
25442550
class ShippingErrorCode(str, Enum):
25452551
ALREADY_EXISTS = "ALREADY_EXISTS"
25462552
GRAPHQL_ERROR = "GRAPHQL_ERROR"
@@ -2689,6 +2695,7 @@ class TransactionUpdateErrorCode(str, Enum):
26892695

26902696
class TransactionRequestActionErrorCode(str, Enum):
26912697
INVALID = "INVALID"
2698+
REQUIRED = "REQUIRED"
26922699
GRAPHQL_ERROR = "GRAPHQL_ERROR"
26932700
NOT_FOUND = "NOT_FOUND"
26942701
MISSING_TRANSACTION_ACTION_REQUEST_WEBHOOK = (

src/saleor_mcp/saleor_client/input_types.py

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -107,30 +107,6 @@ class EventDeliveryFilterInput(BaseModel):
107107
eventType: Optional[WebhookEventTypeEnum] = None
108108

109109

110-
class AttributeChoicesSortingInput(BaseModel):
111-
direction: OrderDirection
112-
field: AttributeChoicesSortField
113-
114-
115-
class AttributeValueFilterInput(BaseModel):
116-
search: Optional[str] = None
117-
ids: Optional[List[str]] = None
118-
slugs: Optional[List[str]] = None
119-
120-
121-
class AttributeValueWhereInput(BaseModel):
122-
ids: Optional[List[str]] = None
123-
name: Optional["StringFilterInput"] = None
124-
slug: Optional["StringFilterInput"] = None
125-
AND: Optional[List["AttributeValueWhereInput"]] = None
126-
OR: Optional[List["AttributeValueWhereInput"]] = None
127-
128-
129-
class StringFilterInput(BaseModel):
130-
eq: Optional[str] = None
131-
oneOf: Optional[List[str]] = None
132-
133-
134110
class AttributeFilterInput(BaseModel):
135111
valueRequired: Optional[bool] = None
136112
isVariantOnly: Optional[bool] = None
@@ -172,6 +148,11 @@ class AttributeWhereInput(BaseModel):
172148
OR: Optional[List["AttributeWhereInput"]] = None
173149

174150

151+
class StringFilterInput(BaseModel):
152+
eq: Optional[str] = None
153+
oneOf: Optional[List[str]] = None
154+
155+
175156
class AttributeInputTypeEnumFilterInput(BaseModel):
176157
eq: Optional[AttributeInputTypeEnum] = None
177158
oneOf: Optional[List[AttributeInputTypeEnum]] = None
@@ -192,6 +173,25 @@ class MeasurementUnitsEnumFilterInput(BaseModel):
192173
oneOf: Optional[List[MeasurementUnitsEnum]] = None
193174

194175

176+
class AttributeChoicesSortingInput(BaseModel):
177+
direction: OrderDirection
178+
field: AttributeChoicesSortField
179+
180+
181+
class AttributeValueFilterInput(BaseModel):
182+
search: Optional[str] = None
183+
ids: Optional[List[str]] = None
184+
slugs: Optional[List[str]] = None
185+
186+
187+
class AttributeValueWhereInput(BaseModel):
188+
ids: Optional[List[str]] = None
189+
name: Optional["StringFilterInput"] = None
190+
slug: Optional["StringFilterInput"] = None
191+
AND: Optional[List["AttributeValueWhereInput"]] = None
192+
OR: Optional[List["AttributeValueWhereInput"]] = None
193+
194+
195195
class ProductFilterInput(BaseModel):
196196
isPublished: Optional[bool] = None
197197
collections: Optional[List[str]] = None
@@ -1098,6 +1098,10 @@ class TimePeriodInputType(BaseModel):
10981098
type: TimePeriodTypeEnum
10991099

11001100

1101+
class RefundSettingsUpdateInput(BaseModel):
1102+
refundReasonReferenceType: str
1103+
1104+
11011105
class ShippingMethodChannelListingInput(BaseModel):
11021106
addChannels: Optional[List["ShippingMethodChannelListingAddInput"]] = None
11031107
removeChannels: Optional[List[str]] = None
@@ -1785,6 +1789,7 @@ class OrderReturnFulfillmentLineInput(BaseModel):
17851789
class OrderGrantRefundCreateInput(BaseModel):
17861790
amount: Optional[Any] = None
17871791
reason: Optional[str] = None
1792+
reasonReference: Optional[str] = None
17881793
lines: Optional[List["OrderGrantRefundCreateLineInput"]] = None
17891794
grantRefundForShipping: Optional[bool] = None
17901795
transactionId: str
@@ -1799,6 +1804,7 @@ class OrderGrantRefundCreateLineInput(BaseModel):
17991804
class OrderGrantRefundUpdateInput(BaseModel):
18001805
amount: Optional[Any] = None
18011806
reason: Optional[str] = None
1807+
reasonReference: Optional[str] = None
18021808
addLines: Optional[List["OrderGrantRefundUpdateLineAddInput"]] = None
18031809
removeLines: Optional[List[str]] = None
18041810
grantRefundForShipping: Optional[bool] = None
@@ -2370,6 +2376,7 @@ class AttributeCreateInput(BaseModel):
23702376
storefrontSearchPosition: Optional[int] = None
23712377
availableInGrid: Optional[bool] = None
23722378
externalReference: Optional[str] = None
2379+
referenceTypes: Optional[List[str]] = None
23732380

23742381

23752382
class AttributeValueCreateInput(BaseModel):
@@ -2396,6 +2403,7 @@ class AttributeUpdateInput(BaseModel):
23962403
storefrontSearchPosition: Optional[int] = None
23972404
availableInGrid: Optional[bool] = None
23982405
externalReference: Optional[str] = None
2406+
referenceTypes: Optional[List[str]] = None
23992407

24002408

24012409
class AttributeValueUpdateInput(BaseModel):
@@ -2553,9 +2561,9 @@ class PermissionGroupUpdateInput(BaseModel):
25532561
restrictedAccessToChannels: Optional[bool] = None
25542562

25552563

2556-
AttributeValueWhereInput.model_rebuild()
25572564
AttributeFilterInput.model_rebuild()
25582565
AttributeWhereInput.model_rebuild()
2566+
AttributeValueWhereInput.model_rebuild()
25592567
ProductFilterInput.model_rebuild()
25602568
AttributeInput.model_rebuild()
25612569
AssignedAttributeValueInput.model_rebuild()

src/saleor_mcp/static/index.html

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,47 @@ <h2 class="card-title">
249249
</div>
250250
</div>
251251

252+
<!-- Customers Tool -->
253+
<div class="accordion-item">
254+
<button class="accordion-trigger">
255+
<div class="accordion-header">
256+
<span class="badge">customers</span>
257+
<span class="tool-name">Customers</span>
258+
</div>
259+
<svg
260+
class="chevron"
261+
fill="none"
262+
stroke="currentColor"
263+
viewBox="0 0 24 24"
264+
>
265+
<path
266+
stroke-linecap="round"
267+
stroke-linejoin="round"
268+
stroke-width="2"
269+
d="M19 9l-7 7-7-7"
270+
/>
271+
</svg>
272+
</button>
273+
<div class="accordion-content">
274+
<p class="tool-description">
275+
Fetch list of customers from Saleor GraphQL API. This tool
276+
retrieves customer information such as: ID, email, first name,
277+
last name, active status, confirmation status, checkout and
278+
order counts, language code, last login, date joined, and
279+
default shipping/billing addresses.
280+
</p>
281+
<li>
282+
first: Number of customers to fetch (max 100 per request).
283+
</li>
284+
<li>
285+
after: Cursor for pagination - fetch customers after this
286+
cursor.
287+
</li>
288+
<li>sort_by: Sort customers by specific field.</li>
289+
<li>where: Filter customers by specific criteria.</li>
290+
</div>
291+
</div>
292+
252293
<!-- Orders Tool -->
253294
<div class="accordion-item">
254295
<button class="accordion-trigger">
@@ -381,7 +422,6 @@ <h4>Arguments:</h4>
381422
returned.
382423
</li>
383424
<li>sort_by: Sort products by specific field.</li>
384-
<li>where: Filter products by specific criteria.</li>
385425
<li>search: Search products with full-text search.</li>
386426
</ul>
387427
</div>

src/saleor_mcp/tools/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
from .channels import channels_router
2+
from .customers import customers_router
23
from .orders import orders_router
34
from .products import products_router
45
from .utils import utils_router
56

6-
__all__ = ["channels_router", "orders_router", "products_router", "utils_router"]
7+
__all__ = [
8+
"channels_router",
9+
"customers_router",
10+
"orders_router",
11+
"products_router",
12+
"utils_router",
13+
]

0 commit comments

Comments
 (0)