kurumera 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kurumera/__init__.py +66 -0
- kurumera/_generated/__init__.py +122 -0
- kurumera/_generated/alias_tools.py +65 -0
- kurumera/_generated/analytics_tools.py +169 -0
- kurumera/_generated/blog_tools.py +100 -0
- kurumera/_generated/branch_tools.py +91 -0
- kurumera/_generated/branding_tools.py +98 -0
- kurumera/_generated/campaign_tools.py +103 -0
- kurumera/_generated/cart_tools.py +58 -0
- kurumera/_generated/collection_tools.py +189 -0
- kurumera/_generated/commercial_tools.py +161 -0
- kurumera/_generated/content_access.py +82 -0
- kurumera/_generated/content_delete.py +49 -0
- kurumera/_generated/crm_file_tools.py +118 -0
- kurumera/_generated/crm_tools.py +1118 -0
- kurumera/_generated/currency_tools.py +72 -0
- kurumera/_generated/customer_tools.py +71 -0
- kurumera/_generated/discount_tools.py +45 -0
- kurumera/_generated/doc_tools.py +102 -0
- kurumera/_generated/email_tools.py +236 -0
- kurumera/_generated/faq_tools.py +50 -0
- kurumera/_generated/finance_tools.py +173 -0
- kurumera/_generated/forecast_tools.py +211 -0
- kurumera/_generated/form_tools.py +64 -0
- kurumera/_generated/gift_card_tools.py +60 -0
- kurumera/_generated/inbox_tools.py +256 -0
- kurumera/_generated/inventory_tools.py +156 -0
- kurumera/_generated/invoice_tools.py +259 -0
- kurumera/_generated/media_library_tools.py +114 -0
- kurumera/_generated/media_tools.py +188 -0
- kurumera/_generated/merge_tools.py +148 -0
- kurumera/_generated/merged_tools.py +249 -0
- kurumera/_generated/migration_tools.py +126 -0
- kurumera/_generated/nav_tools.py +58 -0
- kurumera/_generated/notification_tools.py +45 -0
- kurumera/_generated/order_tools.py +245 -0
- kurumera/_generated/page_locale_tools.py +96 -0
- kurumera/_generated/page_tools.py +106 -0
- kurumera/_generated/pagebuilder_authoring_tools.py +178 -0
- kurumera/_generated/pagebuilder_component_tools.py +75 -0
- kurumera/_generated/pagebuilder_visual_tools.py +42 -0
- kurumera/_generated/pos_tools.py +54 -0
- kurumera/_generated/product_tools.py +248 -0
- kurumera/_generated/review_tools.py +41 -0
- kurumera/_generated/site_gen_tools.py +115 -0
- kurumera/_generated/social_tools.py +165 -0
- kurumera/_generated/store_tools.py +46 -0
- kurumera/_generated/translation_tools.py +67 -0
- kurumera/_generated/webhook_tools.py +58 -0
- kurumera/_transport.py +227 -0
- kurumera/_version.py +1 -0
- kurumera/client.py +266 -0
- kurumera/credentials.py +146 -0
- kurumera/errors.py +264 -0
- kurumera/py.typed +0 -0
- kurumera/registry.json +12990 -0
- kurumera/registry.py +89 -0
- kurumera/types.py +199 -0
- kurumera-0.1.0.dist-info/METADATA +205 -0
- kurumera-0.1.0.dist-info/RECORD +62 -0
- kurumera-0.1.0.dist-info/WHEEL +4 -0
- kurumera-0.1.0.dist-info/licenses/LICENSE +21 -0
kurumera/__init__.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kurumera - drive a Kurumera store from Python.
|
|
3
|
+
|
|
4
|
+
pip install kurumera
|
|
5
|
+
|
|
6
|
+
from kurumera import Kurumera
|
|
7
|
+
km = Kurumera() # KURUMERA_API_KEY from the environment
|
|
8
|
+
km.create_product(title="Badam 500g")
|
|
9
|
+
|
|
10
|
+
Every method is one of the platform's MCP tools, under the same name, reaching
|
|
11
|
+
the same authenticated endpoint. Nothing here decides what you are allowed to
|
|
12
|
+
do: the store, the capabilities and the limits all come from your credential,
|
|
13
|
+
checked server-side exactly as they are for any other client.
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from ._version import __version__
|
|
18
|
+
from .client import Kurumera
|
|
19
|
+
from .credentials import DEFAULT_MCP_URL
|
|
20
|
+
from .errors import (
|
|
21
|
+
AccountError,
|
|
22
|
+
AuthError,
|
|
23
|
+
AuthFailed,
|
|
24
|
+
AuthRequired,
|
|
25
|
+
ConfirmationRequired,
|
|
26
|
+
DestructiveBlockedError,
|
|
27
|
+
InvalidArguments,
|
|
28
|
+
KurumeraConfigError,
|
|
29
|
+
KurumeraConnectionError,
|
|
30
|
+
KurumeraError,
|
|
31
|
+
KurumeraProtocolError,
|
|
32
|
+
NoTenant,
|
|
33
|
+
PermissionDenied,
|
|
34
|
+
RateLimited,
|
|
35
|
+
ReadOnlyModeError,
|
|
36
|
+
ServerError,
|
|
37
|
+
SubscriptionInactive,
|
|
38
|
+
TenantCancelled,
|
|
39
|
+
TenantInactive,
|
|
40
|
+
TenantMismatch,
|
|
41
|
+
TenantPendingApproval,
|
|
42
|
+
ToolCallError,
|
|
43
|
+
ToolNotFound,
|
|
44
|
+
UserInactive,
|
|
45
|
+
UserNotFound,
|
|
46
|
+
)
|
|
47
|
+
from .registry import registry_hash as _registry_hash
|
|
48
|
+
from .registry import tool_count as _tool_count
|
|
49
|
+
from .types import UNSET, Annotations, ToolImage, ToolInfo, ToolResult
|
|
50
|
+
|
|
51
|
+
#: Which tool registry this package was generated from. Report it in a bug.
|
|
52
|
+
REGISTRY_HASH = _registry_hash()
|
|
53
|
+
REGISTRY_TOOL_COUNT = _tool_count()
|
|
54
|
+
|
|
55
|
+
__all__ = [
|
|
56
|
+
"Kurumera",
|
|
57
|
+
"ToolResult", "ToolImage", "ToolInfo", "Annotations", "UNSET",
|
|
58
|
+
"DEFAULT_MCP_URL", "REGISTRY_HASH", "REGISTRY_TOOL_COUNT", "__version__",
|
|
59
|
+
"KurumeraError", "KurumeraConfigError", "KurumeraConnectionError",
|
|
60
|
+
"KurumeraProtocolError", "AuthError", "AuthRequired", "AuthFailed",
|
|
61
|
+
"UserNotFound", "TenantMismatch", "AccountError", "UserInactive", "NoTenant",
|
|
62
|
+
"TenantInactive", "TenantPendingApproval", "TenantCancelled",
|
|
63
|
+
"SubscriptionInactive", "ServerError", "ReadOnlyModeError",
|
|
64
|
+
"DestructiveBlockedError", "ToolCallError", "ToolNotFound",
|
|
65
|
+
"InvalidArguments", "PermissionDenied", "RateLimited", "ConfirmationRequired",
|
|
66
|
+
]
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GENERATED by `python manage.py generate_python_sdk`. Do not edit.
|
|
3
|
+
|
|
4
|
+
Every method is one MCP tool, under the tool's own name, with the tool's own
|
|
5
|
+
documentation. Optional arguments default to UNSET rather than None because the
|
|
6
|
+
server rejects an explicit null for them - see the generator's module docstring.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any, Generic, TypeVar
|
|
11
|
+
|
|
12
|
+
from ..types import UNSET, _Unset
|
|
13
|
+
|
|
14
|
+
R = TypeVar("R")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _ToolBase(Generic[R]):
|
|
18
|
+
"""Supplies `_invoke`. The client decides whether R is a result or a future."""
|
|
19
|
+
|
|
20
|
+
def _invoke(self, name: str, args: dict[str, Any]) -> R: # pragma: no cover
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
from .alias_tools import AliasTools # noqa: E402
|
|
25
|
+
from .analytics_tools import AnalyticsTools # noqa: E402
|
|
26
|
+
from .blog_tools import BlogTools # noqa: E402
|
|
27
|
+
from .branch_tools import BranchTools # noqa: E402
|
|
28
|
+
from .branding_tools import BrandingTools # noqa: E402
|
|
29
|
+
from .campaign_tools import CampaignTools # noqa: E402
|
|
30
|
+
from .cart_tools import CartTools # noqa: E402
|
|
31
|
+
from .collection_tools import CollectionTools # noqa: E402
|
|
32
|
+
from .commercial_tools import CommercialTools # noqa: E402
|
|
33
|
+
from .content_access import ContentAccessTools # noqa: E402
|
|
34
|
+
from .content_delete import ContentDeleteTools # noqa: E402
|
|
35
|
+
from .crm_file_tools import CrmFileTools # noqa: E402
|
|
36
|
+
from .crm_tools import CrmTools # noqa: E402
|
|
37
|
+
from .currency_tools import CurrencyTools # noqa: E402
|
|
38
|
+
from .customer_tools import CustomerTools # noqa: E402
|
|
39
|
+
from .discount_tools import DiscountTools # noqa: E402
|
|
40
|
+
from .doc_tools import DocTools # noqa: E402
|
|
41
|
+
from .email_tools import EmailTools # noqa: E402
|
|
42
|
+
from .faq_tools import FaqTools # noqa: E402
|
|
43
|
+
from .finance_tools import FinanceTools # noqa: E402
|
|
44
|
+
from .forecast_tools import ForecastTools # noqa: E402
|
|
45
|
+
from .form_tools import FormTools # noqa: E402
|
|
46
|
+
from .gift_card_tools import GiftCardTools # noqa: E402
|
|
47
|
+
from .inbox_tools import InboxTools # noqa: E402
|
|
48
|
+
from .inventory_tools import InventoryTools # noqa: E402
|
|
49
|
+
from .invoice_tools import InvoiceTools # noqa: E402
|
|
50
|
+
from .media_library_tools import MediaLibraryTools # noqa: E402
|
|
51
|
+
from .media_tools import MediaTools # noqa: E402
|
|
52
|
+
from .merge_tools import MergeTools # noqa: E402
|
|
53
|
+
from .merged_tools import MergedTools # noqa: E402
|
|
54
|
+
from .migration_tools import MigrationTools # noqa: E402
|
|
55
|
+
from .nav_tools import NavTools # noqa: E402
|
|
56
|
+
from .notification_tools import NotificationTools # noqa: E402
|
|
57
|
+
from .order_tools import OrderTools # noqa: E402
|
|
58
|
+
from .page_locale_tools import PageLocaleTools # noqa: E402
|
|
59
|
+
from .page_tools import PageTools # noqa: E402
|
|
60
|
+
from .pagebuilder_authoring_tools import PagebuilderAuthoringTools # noqa: E402
|
|
61
|
+
from .pagebuilder_component_tools import PagebuilderComponentTools # noqa: E402
|
|
62
|
+
from .pagebuilder_visual_tools import PagebuilderVisualTools # noqa: E402
|
|
63
|
+
from .pos_tools import PosTools # noqa: E402
|
|
64
|
+
from .product_tools import ProductTools # noqa: E402
|
|
65
|
+
from .review_tools import ReviewTools # noqa: E402
|
|
66
|
+
from .site_gen_tools import SiteGenTools # noqa: E402
|
|
67
|
+
from .social_tools import SocialTools # noqa: E402
|
|
68
|
+
from .store_tools import StoreTools # noqa: E402
|
|
69
|
+
from .translation_tools import TranslationTools # noqa: E402
|
|
70
|
+
from .webhook_tools import WebhookTools # noqa: E402
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class GeneratedTools(
|
|
74
|
+
AliasTools[R],
|
|
75
|
+
AnalyticsTools[R],
|
|
76
|
+
BlogTools[R],
|
|
77
|
+
BranchTools[R],
|
|
78
|
+
BrandingTools[R],
|
|
79
|
+
CampaignTools[R],
|
|
80
|
+
CartTools[R],
|
|
81
|
+
CollectionTools[R],
|
|
82
|
+
CommercialTools[R],
|
|
83
|
+
ContentAccessTools[R],
|
|
84
|
+
ContentDeleteTools[R],
|
|
85
|
+
CrmFileTools[R],
|
|
86
|
+
CrmTools[R],
|
|
87
|
+
CurrencyTools[R],
|
|
88
|
+
CustomerTools[R],
|
|
89
|
+
DiscountTools[R],
|
|
90
|
+
DocTools[R],
|
|
91
|
+
EmailTools[R],
|
|
92
|
+
FaqTools[R],
|
|
93
|
+
FinanceTools[R],
|
|
94
|
+
ForecastTools[R],
|
|
95
|
+
FormTools[R],
|
|
96
|
+
GiftCardTools[R],
|
|
97
|
+
InboxTools[R],
|
|
98
|
+
InventoryTools[R],
|
|
99
|
+
InvoiceTools[R],
|
|
100
|
+
MediaLibraryTools[R],
|
|
101
|
+
MediaTools[R],
|
|
102
|
+
MergeTools[R],
|
|
103
|
+
MergedTools[R],
|
|
104
|
+
MigrationTools[R],
|
|
105
|
+
NavTools[R],
|
|
106
|
+
NotificationTools[R],
|
|
107
|
+
OrderTools[R],
|
|
108
|
+
PageLocaleTools[R],
|
|
109
|
+
PageTools[R],
|
|
110
|
+
PagebuilderAuthoringTools[R],
|
|
111
|
+
PagebuilderComponentTools[R],
|
|
112
|
+
PagebuilderVisualTools[R],
|
|
113
|
+
PosTools[R],
|
|
114
|
+
ProductTools[R],
|
|
115
|
+
ReviewTools[R],
|
|
116
|
+
SiteGenTools[R],
|
|
117
|
+
SocialTools[R],
|
|
118
|
+
StoreTools[R],
|
|
119
|
+
TranslationTools[R],
|
|
120
|
+
WebhookTools[R],
|
|
121
|
+
):
|
|
122
|
+
"""Every tool the platform exposed when this package was built."""
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GENERATED by `python manage.py generate_python_sdk`. Do not edit.
|
|
3
|
+
|
|
4
|
+
Tools from mcp_server/tools/alias_tools.py.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, TypeVar
|
|
9
|
+
|
|
10
|
+
from ..types import UNSET, _Unset
|
|
11
|
+
from . import _ToolBase
|
|
12
|
+
|
|
13
|
+
R = TypeVar("R")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AliasTools(_ToolBase[R]):
|
|
17
|
+
def add_search_aliases(self, content_type: str, item_id: str, terms: list[Any], *, confirm: bool | _Unset = UNSET) -> R:
|
|
18
|
+
"""
|
|
19
|
+
Requires confirm=True.
|
|
20
|
+
|
|
21
|
+
Make a product findable by extra words shoppers actually type.
|
|
22
|
+
|
|
23
|
+
Good aliases: local names ("Motia" for jasmine), transliterations
|
|
24
|
+
("موتیا"), spelling variants ("Motiya"), common phrases ("motia ka poda"),
|
|
25
|
+
and old names customers still use.
|
|
26
|
+
|
|
27
|
+
Bad aliases: generic words like "plant" or "gift" — they make the product
|
|
28
|
+
match searches it has no business appearing in, which pushes down results
|
|
29
|
+
that genuinely match.
|
|
30
|
+
|
|
31
|
+
Aliases are invisible on the storefront and take effect immediately. They
|
|
32
|
+
change what search finds, never what a shopper reads.
|
|
33
|
+
|
|
34
|
+
Omitted arguments are not sent; the store applies its own defaults: confirm=False.
|
|
35
|
+
"""
|
|
36
|
+
return self._invoke("add_search_aliases", {"content_type": content_type, "item_id": item_id, "terms": terms, "confirm": confirm})
|
|
37
|
+
|
|
38
|
+
def list_search_aliases(self, *, content_type: str | _Unset = UNSET, item_id: str | _Unset = UNSET) -> R:
|
|
39
|
+
"""
|
|
40
|
+
Read-only.
|
|
41
|
+
|
|
42
|
+
The extra search terms attached to a product (or the whole store).
|
|
43
|
+
|
|
44
|
+
Omit `item_id` for a store-wide view — useful for spotting which products
|
|
45
|
+
have no local-language terms yet and would therefore be invisible to a
|
|
46
|
+
shopper searching in Urdu or Roman Urdu.
|
|
47
|
+
|
|
48
|
+
Omitted arguments are not sent; the store applies its own defaults: content_type='product'.
|
|
49
|
+
"""
|
|
50
|
+
return self._invoke("list_search_aliases", {"content_type": content_type, "item_id": item_id})
|
|
51
|
+
|
|
52
|
+
def remove_search_aliases(self, content_type: str, item_id: str, terms: list[Any], *, confirm: bool | _Unset = UNSET) -> R:
|
|
53
|
+
"""
|
|
54
|
+
DESTRUCTIVE - removes, overwrites or makes something irreversibly live.
|
|
55
|
+
Requires confirm=True.
|
|
56
|
+
|
|
57
|
+
Remove search terms from a product.
|
|
58
|
+
|
|
59
|
+
Use when an alias is pulling the product into searches it shouldn't match.
|
|
60
|
+
Removing one only narrows what search finds — it never hides the product
|
|
61
|
+
itself.
|
|
62
|
+
|
|
63
|
+
Omitted arguments are not sent; the store applies its own defaults: confirm=False.
|
|
64
|
+
"""
|
|
65
|
+
return self._invoke("remove_search_aliases", {"content_type": content_type, "item_id": item_id, "terms": terms, "confirm": confirm})
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GENERATED by `python manage.py generate_python_sdk`. Do not edit.
|
|
3
|
+
|
|
4
|
+
Tools from mcp_server/tools/analytics_tools.py.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, TypeVar
|
|
9
|
+
|
|
10
|
+
from ..types import UNSET, _Unset
|
|
11
|
+
from . import _ToolBase
|
|
12
|
+
|
|
13
|
+
R = TypeVar("R")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AnalyticsTools(_ToolBase[R]):
|
|
17
|
+
def generate_business_report(self, report_type: str, *, baseline_from: str | _Unset = UNSET, baseline_label: str | _Unset = UNSET, baseline_to: str | _Unset = UNSET, compare: bool | _Unset = UNSET, date_from: str | _Unset = UNSET, date_to: str | _Unset = UNSET, days: int | _Unset = UNSET, theme: str | _Unset = UNSET) -> R:
|
|
18
|
+
"""
|
|
19
|
+
Read-only.
|
|
20
|
+
|
|
21
|
+
A whole branded report in one call — ordered sections, each with its
|
|
22
|
+
numbers, its chart and the reference that traces it to the call behind it.
|
|
23
|
+
|
|
24
|
+
Enough to assemble a deck without asking a second question and without
|
|
25
|
+
reading a pixel.
|
|
26
|
+
|
|
27
|
+
report_type:
|
|
28
|
+
weekly_management How the week went, sales, what sold, payment states.
|
|
29
|
+
merchant_performance Headline, gross-to-net, best sellers, customers.
|
|
30
|
+
agency_client Results, visitors, sources, visit-to-purchase.
|
|
31
|
+
product_review By product, by units, stock on hand, the funnel.
|
|
32
|
+
investor_evidence Headline, gross-to-net, revenue, growth — as
|
|
33
|
+
EVIDENCE charts, provenance stamped on each image.
|
|
34
|
+
bank_evidence Gross-to-net, payment states, tax, refunds — also
|
|
35
|
+
evidence charts.
|
|
36
|
+
enterprise_case_study Headline, growth, customers, what sells — as
|
|
37
|
+
evidence charts, because a prospect handed a
|
|
38
|
+
growth figure cannot check it otherwise.
|
|
39
|
+
migration Before and after, against a baseline YOU state.
|
|
40
|
+
Needs baseline_from, baseline_to and
|
|
41
|
+
baseline_label; see below.
|
|
42
|
+
|
|
43
|
+
BEFORE/AFTER (migration)
|
|
44
|
+
baseline_from/_to The window the store traded in BEFORE the change,
|
|
45
|
+
YYYY-MM-DD. Must end before the reported period
|
|
46
|
+
opens — an overlapping baseline counts the same
|
|
47
|
+
trading on both sides and is refused, not caveated.
|
|
48
|
+
baseline_label What that window WAS, in your words: "trading on the
|
|
49
|
+
old platform", "the quarter before launch". Required,
|
|
50
|
+
because a reader shown two numbers and told nothing
|
|
51
|
+
about the first one has not been shown a comparison.
|
|
52
|
+
|
|
53
|
+
Every section runs TWICE, once per window, through this same tool — so
|
|
54
|
+
before and after are one definition, and each half carries its own
|
|
55
|
+
reference and its own stamped chart. Unequal window lengths are allowed
|
|
56
|
+
and stated; a baseline in which Kurumera recorded no orders at all is
|
|
57
|
+
called out, because rendering it as zero turns a migration date into
|
|
58
|
+
growth.
|
|
59
|
+
|
|
60
|
+
THIS COMPUTES NOTHING. Every figure comes from `get_report` and every
|
|
61
|
+
colour from the brand kit, so a section you could not read directly you
|
|
62
|
+
cannot read here either: the finance scope and the identity redaction apply
|
|
63
|
+
exactly as they do to a direct call.
|
|
64
|
+
|
|
65
|
+
A section that cannot be produced is MARKED, never filled. Check
|
|
66
|
+
`summary.complete` and `summary.warnings` before presenting the report, and
|
|
67
|
+
say plainly which parts are missing rather than working around the hole —
|
|
68
|
+
a gap filled with a plausible number is the one failure that makes a report
|
|
69
|
+
dangerous rather than merely incomplete.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
JSON: { report_type, brand: {...}, sections: [ { report, title,
|
|
73
|
+
available, data, chart, reference, reason } ],
|
|
74
|
+
summary: { sections_requested, sections_available, complete,
|
|
75
|
+
warnings } }
|
|
76
|
+
|
|
77
|
+
Omitted arguments are not sent; the store applies its own defaults: compare=True, days=30, theme='light'.
|
|
78
|
+
"""
|
|
79
|
+
return self._invoke("generate_business_report", {"report_type": report_type, "baseline_from": baseline_from, "baseline_label": baseline_label, "baseline_to": baseline_to, "compare": compare, "date_from": date_from, "date_to": date_to, "days": days, "theme": theme})
|
|
80
|
+
|
|
81
|
+
def get_report(self, report: str, *, city: str | _Unset = UNSET, compare: bool | _Unset = UNSET, country: str | _Unset = UNSET, date_from: str | _Unset = UNSET, date_to: str | _Unset = UNSET, days: int | _Unset = UNSET, group_by: str | _Unset = UNSET, limit: int | _Unset = UNSET, location_id: str | _Unset = UNSET, max_cohorts: int | _Unset = UNSET, render: str | _Unset = UNSET, theme: str | _Unset = UNSET) -> R:
|
|
82
|
+
"""
|
|
83
|
+
Read-only.
|
|
84
|
+
|
|
85
|
+
Every analytics and reporting read for this store, selected by `report`.
|
|
86
|
+
|
|
87
|
+
Window: `days` (default 30, inclusive of today) OR explicit `date_from` /
|
|
88
|
+
`date_to` (YYYY-MM-DD). The extra args apply only to the reports that name
|
|
89
|
+
them below; the rest are ignored.
|
|
90
|
+
|
|
91
|
+
Every response carries `_meta` alongside the report's own keys: the store,
|
|
92
|
+
its CURRENCY and TIMEZONE, the exact window, when it was generated, and a
|
|
93
|
+
"Generated from Kurumera" source line. Quote the currency whenever you
|
|
94
|
+
quote a figure — "16,084" on its own is not a fact anybody can check.
|
|
95
|
+
|
|
96
|
+
`compare=True` adds `_meta.comparison`: the same report over the span of
|
|
97
|
+
equal length immediately before, so a week can be read against the week
|
|
98
|
+
before it. Refused for inventory_valuation, live_snapshot and rfm, which
|
|
99
|
+
describe a moment rather than a span.
|
|
100
|
+
|
|
101
|
+
Reports that STATE MONEY — sales_breakdown, financial_summary, tax,
|
|
102
|
+
refunds, inventory_valuation, pos_till, branch_sales — need `read_orders`
|
|
103
|
+
as well as `read_analytics`. Trading reports (summary, sales,
|
|
104
|
+
revenue_by_day, top_products) need only the latter. Each money report
|
|
105
|
+
returns a `definitions` block saying what its figures mean; quote the
|
|
106
|
+
definition alongside the number.
|
|
107
|
+
|
|
108
|
+
Customer identities are REDACTED unless you also hold the `read_customers`
|
|
109
|
+
capability: names become "Customer 1", contact details are emptied, and
|
|
110
|
+
every aggregate — spend, order counts, segments, scores — is untouched.
|
|
111
|
+
`_meta.redaction` says which happened (`identities`, `none`, or
|
|
112
|
+
`not_applicable`). Do not present a redacted name as if it were real.
|
|
113
|
+
|
|
114
|
+
`render='evidence'` draws the same chart with the store, the exact window,
|
|
115
|
+
the timezone, the currency, the generation time and the traceable reference
|
|
116
|
+
stamped ON the image — for an audit or a file, where the chart is handed
|
|
117
|
+
over on its own and its context cannot live in a response somebody else is
|
|
118
|
+
holding.
|
|
119
|
+
|
|
120
|
+
`render='svg'` adds `chart`: the same numbers drawn as a 1920×1080 SVG,
|
|
121
|
+
sized and labelled for a 16:9 slide and carrying its own period and
|
|
122
|
+
currency caption. `theme='dark'` draws it for a dark deck. The SVG IS the
|
|
123
|
+
editable artefact — open it in any vector tool, or restyle it from the
|
|
124
|
+
structured data returned beside it. Only reports with a real chart form
|
|
125
|
+
render: sales, revenue_by_day, orders_by_day, product_performance,
|
|
126
|
+
top_products and summary. Anything else is refused rather than forced into
|
|
127
|
+
a shape it does not have.
|
|
128
|
+
|
|
129
|
+
report:
|
|
130
|
+
summary Revenue, orders, AOV, new customers.
|
|
131
|
+
sales Revenue/orders over time. Set group_by=day|week|month.
|
|
132
|
+
orders_by_day Daily order counts.
|
|
133
|
+
revenue_by_day Daily revenue totals.
|
|
134
|
+
top_products Best sellers by units. Set limit.
|
|
135
|
+
product_performance Units/revenue/orders. Set limit, and
|
|
136
|
+
group_by=product|variant|category. `variant`
|
|
137
|
+
answers which SIZE sells, which the product row
|
|
138
|
+
averages away. No margin column: unit costs are
|
|
139
|
+
recorded on under 1% of line items, so one would
|
|
140
|
+
be null for almost every row.
|
|
141
|
+
sales_breakdown Gross → discounts → refunds → NET SALES, plus tax,
|
|
142
|
+
shipping and total charged. Every definition is in
|
|
143
|
+
the response; tax and shipping are stated BESIDE
|
|
144
|
+
net sales, never inside it. Check `reconciles`
|
|
145
|
+
before quoting the figures.
|
|
146
|
+
financial_summary Financial + fulfillment status breakdown.
|
|
147
|
+
tax Tax collected.
|
|
148
|
+
refunds Refunds issued.
|
|
149
|
+
inventory_valuation Stock valuation at cost and retail. No window.
|
|
150
|
+
live_snapshot Active visitors, recent events, live orders. No window.
|
|
151
|
+
traffic Sessions / pageviews / visitors trend.
|
|
152
|
+
acquisition Referrers / channels / UTM sources.
|
|
153
|
+
geography Sales + sessions by country/city. Filter country=, city=.
|
|
154
|
+
behavior Top pages, entry/exit, engagement. Set limit.
|
|
155
|
+
product_behavior Per-product view to cart to purchase funnel. Set limit.
|
|
156
|
+
conversion_funnel Storewide visit to view to cart to purchase.
|
|
157
|
+
checkout_funnel Checkout steps started through completed.
|
|
158
|
+
customer_acquisition New vs returning customers.
|
|
159
|
+
cohorts Retention by first-order month. Set max_cohorts.
|
|
160
|
+
rfm RFM segments. No window.
|
|
161
|
+
search Top on-site searches + no-results. Set limit.
|
|
162
|
+
branch_sales Sales per branch. Filter location_id (see list_locations).
|
|
163
|
+
pos_till POS takings by tender. Filter location_id.
|
|
164
|
+
|
|
165
|
+
Returns: JSON for the chosen report.
|
|
166
|
+
|
|
167
|
+
Omitted arguments are not sent; the store applies its own defaults: compare=False, days=30, group_by='day', limit=20, max_cohorts=12, theme='light'.
|
|
168
|
+
"""
|
|
169
|
+
return self._invoke("get_report", {"report": report, "city": city, "compare": compare, "country": country, "date_from": date_from, "date_to": date_to, "days": days, "group_by": group_by, "limit": limit, "location_id": location_id, "max_cohorts": max_cohorts, "render": render, "theme": theme})
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GENERATED by `python manage.py generate_python_sdk`. Do not edit.
|
|
3
|
+
|
|
4
|
+
Tools from mcp_server/tools/blog_tools.py.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, TypeVar
|
|
9
|
+
|
|
10
|
+
from ..types import UNSET, _Unset
|
|
11
|
+
from . import _ToolBase
|
|
12
|
+
|
|
13
|
+
R = TypeVar("R")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BlogTools(_ToolBase[R]):
|
|
17
|
+
def create_article(self, blog_id: str, title: str, *, author_name: str | _Unset = UNSET, body_html: str | _Unset = UNSET, canonical_url: str | _Unset = UNSET, handle: str | _Unset = UNSET, image_alt: str | _Unset = UNSET, image_url: str | _Unset = UNSET, noindex: bool | _Unset = UNSET, published: bool | _Unset = UNSET, seo_description: str | _Unset = UNSET, seo_title: str | _Unset = UNSET, summary_html: str | _Unset = UNSET, tags: list[Any] | _Unset = UNSET) -> R:
|
|
18
|
+
"""
|
|
19
|
+
Not idempotent - repeating it may act twice.
|
|
20
|
+
|
|
21
|
+
Write a blog article and optionally publish it.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
blog_id: UUID or handle of the blog to post in (required).
|
|
25
|
+
title: Article title (required).
|
|
26
|
+
body_html: Full article body (HTML — sanitized on save).
|
|
27
|
+
summary_html: Optional excerpt/teaser HTML (auto-generated from the body
|
|
28
|
+
if left blank).
|
|
29
|
+
author_name: Display author name.
|
|
30
|
+
tags: List of tag strings.
|
|
31
|
+
handle: URL slug (`…/blog/<blog>/<handle>`). Auto-generated from the
|
|
32
|
+
title + de-duplicated within the blog if omitted.
|
|
33
|
+
image_url / image_alt: Featured / social-share image + alt text.
|
|
34
|
+
seo_title / seo_description: Meta title (≤ 70) + description (≤ 320).
|
|
35
|
+
canonical_url: Absolute canonical URL (leave blank normally).
|
|
36
|
+
noindex: True to hide from search engines.
|
|
37
|
+
published: True to publish now, False to save as a draft (default).
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The created article.
|
|
41
|
+
|
|
42
|
+
Omitted arguments are not sent; the store applies its own defaults: noindex=False, published=False.
|
|
43
|
+
"""
|
|
44
|
+
return self._invoke("create_article", {"blog_id": blog_id, "title": title, "author_name": author_name, "body_html": body_html, "canonical_url": canonical_url, "handle": handle, "image_alt": image_alt, "image_url": image_url, "noindex": noindex, "published": published, "seo_description": seo_description, "seo_title": seo_title, "summary_html": summary_html, "tags": tags})
|
|
45
|
+
|
|
46
|
+
def create_blog(self, title: str, *, commentable: str | _Unset = UNSET, feedburner_url: str | _Unset = UNSET, handle: str | _Unset = UNSET, seo_description: str | _Unset = UNSET, seo_title: str | _Unset = UNSET, template_suffix: str | _Unset = UNSET) -> R:
|
|
47
|
+
"""
|
|
48
|
+
Not idempotent - repeating it may act twice.
|
|
49
|
+
|
|
50
|
+
Create a new blog container.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
title: Blog name (required), e.g. 'Plant Care Guides'.
|
|
54
|
+
handle: URL slug (`…/blog/<handle>`). Auto-generated from the
|
|
55
|
+
title and de-duplicated if omitted or already taken.
|
|
56
|
+
commentable: 'NO' (default) | 'MODERATE' | 'YES'.
|
|
57
|
+
seo_title: Meta title (≤ 70 chars).
|
|
58
|
+
seo_description: Meta description (≤ 320 chars).
|
|
59
|
+
feedburner_url: Optional RSS/FeedBurner URL.
|
|
60
|
+
template_suffix: Optional storefront template suffix.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
The created blog.
|
|
64
|
+
|
|
65
|
+
Omitted arguments are not sent; the store applies its own defaults: commentable='NO'.
|
|
66
|
+
"""
|
|
67
|
+
return self._invoke("create_blog", {"title": title, "commentable": commentable, "feedburner_url": feedburner_url, "handle": handle, "seo_description": seo_description, "seo_title": seo_title, "template_suffix": template_suffix})
|
|
68
|
+
|
|
69
|
+
def update_article(self, article_id: str, *, author_name: str | _Unset = UNSET, blog_id: str | _Unset = UNSET, body_html: str | _Unset = UNSET, canonical_url: str | _Unset = UNSET, handle: str | _Unset = UNSET, image_alt: str | _Unset = UNSET, image_url: str | _Unset = UNSET, noindex: bool | _Unset = UNSET, published: bool | _Unset = UNSET, seo_description: str | _Unset = UNSET, seo_title: str | _Unset = UNSET, summary_html: str | _Unset = UNSET, tags: list[Any] | _Unset = UNSET, title: str | _Unset = UNSET) -> R:
|
|
70
|
+
"""
|
|
71
|
+
Update an article. Any argument left as None is unchanged.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
article_id: UUID of the article (must belong to your tenant).
|
|
75
|
+
blog_id: Move the article to a different blog (UUID or handle).
|
|
76
|
+
handle: New URL slug — slugified + de-duplicated within the blog.
|
|
77
|
+
published: True to publish, False to revert to a draft.
|
|
78
|
+
(other args mirror create_article; body_html/summary_html are sanitized.)
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
The updated article.
|
|
82
|
+
"""
|
|
83
|
+
return self._invoke("update_article", {"article_id": article_id, "author_name": author_name, "blog_id": blog_id, "body_html": body_html, "canonical_url": canonical_url, "handle": handle, "image_alt": image_alt, "image_url": image_url, "noindex": noindex, "published": published, "seo_description": seo_description, "seo_title": seo_title, "summary_html": summary_html, "tags": tags, "title": title})
|
|
84
|
+
|
|
85
|
+
def update_blog(self, blog_id: str, *, commentable: str | _Unset = UNSET, feedburner_url: str | _Unset = UNSET, handle: str | _Unset = UNSET, seo_description: str | _Unset = UNSET, seo_title: str | _Unset = UNSET, template_suffix: str | _Unset = UNSET, title: str | _Unset = UNSET) -> R:
|
|
86
|
+
"""
|
|
87
|
+
Update a blog. Any argument left as None is unchanged.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
blog_id: UUID or handle of the blog (must belong to your tenant).
|
|
91
|
+
handle: New URL slug — slugified + de-duplicated. NOTE: changing a
|
|
92
|
+
blog handle changes its public URL and does NOT auto-create
|
|
93
|
+
a redirect, so only rename handles for blogs with no traffic.
|
|
94
|
+
commentable: 'NO' | 'MODERATE' | 'YES'.
|
|
95
|
+
(other args mirror create_blog.)
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
The updated blog.
|
|
99
|
+
"""
|
|
100
|
+
return self._invoke("update_blog", {"blog_id": blog_id, "commentable": commentable, "feedburner_url": feedburner_url, "handle": handle, "seo_description": seo_description, "seo_title": seo_title, "template_suffix": template_suffix, "title": title})
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GENERATED by `python manage.py generate_python_sdk`. Do not edit.
|
|
3
|
+
|
|
4
|
+
Tools from mcp_server/tools/branch_tools.py.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, TypeVar
|
|
9
|
+
|
|
10
|
+
from ..types import UNSET, _Unset
|
|
11
|
+
from . import _ToolBase
|
|
12
|
+
|
|
13
|
+
R = TypeVar("R")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BranchTools(_ToolBase[R]):
|
|
17
|
+
def create_branch(self, name: str, *, address: dict[str, Any] | _Unset = UNSET, confirm: bool | _Unset = UNSET, fulfills_online_orders: bool | _Unset = UNSET, is_pos_branch: bool | _Unset = UNSET) -> R:
|
|
18
|
+
"""
|
|
19
|
+
Requires confirm=True.
|
|
20
|
+
Not idempotent - repeating it may act twice.
|
|
21
|
+
|
|
22
|
+
Create a new branch/location (a shop or warehouse). is_pos_branch=True
|
|
23
|
+
makes it a physical sales branch that can run a POS counter; set
|
|
24
|
+
fulfills_online_orders=True if it should also ship web orders. Structural
|
|
25
|
+
change — requires confirm=True after the user approves.
|
|
26
|
+
|
|
27
|
+
Omitted arguments are not sent; the store applies its own defaults: confirm=False, fulfills_online_orders=False, is_pos_branch=True.
|
|
28
|
+
"""
|
|
29
|
+
return self._invoke("create_branch", {"name": name, "address": address, "confirm": confirm, "fulfills_online_orders": fulfills_online_orders, "is_pos_branch": is_pos_branch})
|
|
30
|
+
|
|
31
|
+
def create_staff_member(self, email: str, *, branch_ids: list[Any] | _Unset = UNSET, confirm: bool | _Unset = UNSET, first_name: str | _Unset = UNSET, last_name: str | _Unset = UNSET, permissions: list[Any] | _Unset = UNSET, role_id: str | _Unset = UNSET) -> R:
|
|
32
|
+
"""
|
|
33
|
+
Requires confirm=True.
|
|
34
|
+
Reaches outside the store (sends mail, calls a gateway, publishes).
|
|
35
|
+
Not idempotent - repeating it may act twice.
|
|
36
|
+
|
|
37
|
+
Invite a staff member (e.g. a branch manager): creates an inactive
|
|
38
|
+
account and emails them a set-password link (or promotes an existing
|
|
39
|
+
customer account in place). `branch_ids` scopes them to those branches
|
|
40
|
+
(empty = all branches); `permissions` grants capabilities such as
|
|
41
|
+
read_orders/write_orders/read_pos (see the store's roles for examples).
|
|
42
|
+
Grants access to the store — requires confirm=True after the user approves.
|
|
43
|
+
|
|
44
|
+
Omitted arguments are not sent; the store applies its own defaults: confirm=False.
|
|
45
|
+
"""
|
|
46
|
+
return self._invoke("create_staff_member", {"email": email, "branch_ids": branch_ids, "confirm": confirm, "first_name": first_name, "last_name": last_name, "permissions": permissions, "role_id": role_id})
|
|
47
|
+
|
|
48
|
+
def list_staff(self) -> R:
|
|
49
|
+
"""
|
|
50
|
+
Read-only.
|
|
51
|
+
|
|
52
|
+
List this store's staff members with their role, per-user capabilities and
|
|
53
|
+
assigned branches (empty branch list = all branches / head-office access).
|
|
54
|
+
Call this before set_staff_access to find the right user_id.
|
|
55
|
+
"""
|
|
56
|
+
return self._invoke("list_staff", {})
|
|
57
|
+
|
|
58
|
+
def set_staff_access(self, user_id: str, *, branch_ids: list[Any] | _Unset = UNSET, confirm: bool | _Unset = UNSET, permissions: list[Any] | _Unset = UNSET, role_id: str | _Unset = UNSET) -> R:
|
|
59
|
+
"""
|
|
60
|
+
DESTRUCTIVE - removes, overwrites or makes something irreversibly live.
|
|
61
|
+
Requires confirm=True.
|
|
62
|
+
|
|
63
|
+
Change a staff member's access: which branches they cover (empty list =
|
|
64
|
+
all branches), their per-user capabilities, and/or their role — e.g. make
|
|
65
|
+
someone the manager of a branch. Only the fields you pass change; the
|
|
66
|
+
others are left as they are. Changes what this person can do — requires
|
|
67
|
+
confirm=True after the user approves.
|
|
68
|
+
|
|
69
|
+
Omitted arguments are not sent; the store applies its own defaults: confirm=False.
|
|
70
|
+
"""
|
|
71
|
+
return self._invoke("set_staff_access", {"user_id": user_id, "branch_ids": branch_ids, "confirm": confirm, "permissions": permissions, "role_id": role_id})
|
|
72
|
+
|
|
73
|
+
def transfer_stock(self, from_location_id: str, to_location_id: str, lines: list[Any], *, confirm: bool | _Unset = UNSET, note: str | _Unset = UNSET, reason: str | _Unset = UNSET, reference_document_uri: str | _Unset = UNSET) -> R:
|
|
74
|
+
"""
|
|
75
|
+
Requires confirm=True.
|
|
76
|
+
Not idempotent - repeating it may act twice.
|
|
77
|
+
|
|
78
|
+
Move stock between branches. `lines` is a list of
|
|
79
|
+
{"variant_id": "<uuid>", "quantity": <int>} (max 100). All-or-nothing: any
|
|
80
|
+
under-stocked line rolls the whole transfer back. Physically relocates
|
|
81
|
+
inventory — requires confirm=True after the user approves the summary.
|
|
82
|
+
Use list_locations for branch ids and get_inventory_levels for stock.
|
|
83
|
+
`note` is free text kept on every line's ledger entry ("restocking Gulberg
|
|
84
|
+
before Eid"): the reason says what kind of movement this is, the note says
|
|
85
|
+
why this one happened. `reference_document_uri` is an optional http/https
|
|
86
|
+
link to the paperwork (a transfer note, a signed handover) kept on both
|
|
87
|
+
legs of every line.
|
|
88
|
+
|
|
89
|
+
Omitted arguments are not sent; the store applies its own defaults: confirm=False, reason='transfer'.
|
|
90
|
+
"""
|
|
91
|
+
return self._invoke("transfer_stock", {"from_location_id": from_location_id, "to_location_id": to_location_id, "lines": lines, "confirm": confirm, "note": note, "reason": reason, "reference_document_uri": reference_document_uri})
|