nocfo-cli 1.4.1__tar.gz → 1.4.3__tar.gz
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.
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/PKG-INFO +1 -1
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/pyproject.toml +1 -1
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/app.py +9 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/server.py +15 -17
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/LICENSE +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/README.md +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/__init__.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/api_client.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/__init__.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/__init__.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/_helpers.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/accounts.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/auth.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/businesses.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/contacts.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/documents.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/files.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/invoices.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/products.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/purchase_invoices.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/reports.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/schema.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/tags.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/user.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/context.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/output.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/config.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/__init__.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/auth.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/contract_validation.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/error_handling.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/http_error_capture.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/middleware.py +0 -0
- {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/openapi.py +0 -0
|
@@ -103,6 +103,14 @@ def run_mcp_server(
|
|
|
103
103
|
"--required-scopes",
|
|
104
104
|
help="Comma-separated OAuth scopes required for MCP tools.",
|
|
105
105
|
),
|
|
106
|
+
stateless_http: bool = typer.Option(
|
|
107
|
+
False,
|
|
108
|
+
"--stateless-http/--stateful-http",
|
|
109
|
+
help=(
|
|
110
|
+
"Use stateless streamable HTTP mode (recommended behind "
|
|
111
|
+
"load balancers with multiple MCP tasks)."
|
|
112
|
+
),
|
|
113
|
+
),
|
|
106
114
|
) -> None:
|
|
107
115
|
"""Run NoCFO MCP server over stdio or HTTP transport.
|
|
108
116
|
|
|
@@ -135,6 +143,7 @@ def run_mcp_server(
|
|
|
135
143
|
auth_mode=auth_mode_value,
|
|
136
144
|
mcp_base_url=mcp_base_url or os.getenv("NOCFO_MCP_BASE_URL"),
|
|
137
145
|
required_scopes=scope_items,
|
|
146
|
+
stateless_http=stateless_http,
|
|
138
147
|
)
|
|
139
148
|
|
|
140
149
|
if transport_normalized == "http":
|
|
@@ -66,26 +66,16 @@ def _normalize_mcp_namespace_token(value: str) -> str:
|
|
|
66
66
|
def build_mcp_component_name(
|
|
67
67
|
operation_id: str, extensions: dict[str, Any] | None
|
|
68
68
|
) -> str:
|
|
69
|
-
"""Build MCP name
|
|
69
|
+
"""Build MCP component name from ``operation_id``.
|
|
70
70
|
|
|
71
|
-
Namespace
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
Namespace extension values are preserved in metadata but are not used for
|
|
72
|
+
display-name generation to keep backend ``operationId`` as the single source
|
|
73
|
+
of truth.
|
|
74
74
|
"""
|
|
75
|
+
del extensions
|
|
75
76
|
if not operation_id or not str(operation_id).strip():
|
|
76
77
|
return operation_id
|
|
77
|
-
|
|
78
|
-
if not isinstance(raw, str) or not raw.strip():
|
|
79
|
-
return operation_id
|
|
80
|
-
ns = _normalize_mcp_namespace_token(raw)
|
|
81
|
-
if not ns:
|
|
82
|
-
return operation_id
|
|
83
|
-
# Avoid duplicating the namespace if operation_id already starts with it.
|
|
84
|
-
# Example: operation_id "invoicing.contact.create" with ns "invoicing"
|
|
85
|
-
# should become "invoicing_contact_create", not "invoicing_invoicing_contact_create".
|
|
86
|
-
if operation_id.startswith(f"{ns}."):
|
|
87
|
-
operation_id = operation_id[len(ns) + 1 :]
|
|
88
|
-
return f"{ns}_{operation_id.replace('.', '_')}"
|
|
78
|
+
return operation_id.replace(".", "_")
|
|
89
79
|
|
|
90
80
|
|
|
91
81
|
def _resource_uri_with_name(uri: str | AnyUrl, display_name: str) -> AnyUrl:
|
|
@@ -178,6 +168,7 @@ class MCPServerOptions:
|
|
|
178
168
|
jwt_exchange_path: str = "/auth/jwt/"
|
|
179
169
|
token_refresh_skew_seconds: int = 60
|
|
180
170
|
required_scopes: tuple[str, ...] = ()
|
|
171
|
+
stateless_http: bool = False
|
|
181
172
|
|
|
182
173
|
|
|
183
174
|
def _create_pat_client(
|
|
@@ -298,7 +289,14 @@ def run_http_server(
|
|
|
298
289
|
"""Run NoCFO MCP server over streamable HTTP transport."""
|
|
299
290
|
|
|
300
291
|
server = create_server(config, options=options)
|
|
301
|
-
|
|
292
|
+
opts = options or MCPServerOptions()
|
|
293
|
+
server.run(
|
|
294
|
+
transport="http",
|
|
295
|
+
host=host,
|
|
296
|
+
port=port,
|
|
297
|
+
path=path,
|
|
298
|
+
stateless_http=opts.stateless_http,
|
|
299
|
+
)
|
|
302
300
|
|
|
303
301
|
|
|
304
302
|
async def run_server_async(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|