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.
Files changed (34) hide show
  1. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/PKG-INFO +1 -1
  2. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/pyproject.toml +1 -1
  3. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/app.py +9 -0
  4. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/server.py +15 -17
  5. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/LICENSE +0 -0
  6. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/README.md +0 -0
  7. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/__init__.py +0 -0
  8. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/api_client.py +0 -0
  9. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/__init__.py +0 -0
  10. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/__init__.py +0 -0
  11. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/_helpers.py +0 -0
  12. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/accounts.py +0 -0
  13. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/auth.py +0 -0
  14. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/businesses.py +0 -0
  15. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/contacts.py +0 -0
  16. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/documents.py +0 -0
  17. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/files.py +0 -0
  18. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/invoices.py +0 -0
  19. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/products.py +0 -0
  20. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/purchase_invoices.py +0 -0
  21. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/reports.py +0 -0
  22. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/schema.py +0 -0
  23. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/tags.py +0 -0
  24. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/commands/user.py +0 -0
  25. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/context.py +0 -0
  26. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/cli/output.py +0 -0
  27. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/config.py +0 -0
  28. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/__init__.py +0 -0
  29. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/auth.py +0 -0
  30. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/contract_validation.py +0 -0
  31. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/error_handling.py +0 -0
  32. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/http_error_capture.py +0 -0
  33. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/mcp/middleware.py +0 -0
  34. {nocfo_cli-1.4.1 → nocfo_cli-1.4.3}/src/nocfo_toolkit/openapi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nocfo-cli
3
- Version: 1.4.1
3
+ Version: 1.4.3
4
4
  Summary: NoCFO CLI, MCP server, and Cursor skill toolkit.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "nocfo-cli"
7
- version = "1.4.1"
7
+ version = "1.4.3"
8
8
  description = "NoCFO CLI, MCP server, and Cursor skill toolkit."
9
9
  authors = ["NoCFO"]
10
10
  readme = "README.md"
@@ -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 ``<x-mcp-namespace>_<operation_id_with_dots_as_underscores>``.
69
+ """Build MCP component name from ``operation_id``.
70
70
 
71
- Namespace is read from the OpenAPI operation extension ``x-mcp-namespace`` (set in
72
- the backend via ``mcp_extend_schema``). If missing, ``operation_id`` is
73
- returned unchanged.
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
- raw = (extensions or {}).get(X_MCP_NAMESPACE)
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
- server.run(transport="http", host=host, port=port, path=path)
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