nocfo-cli 1.3.0__tar.gz → 1.4.0__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.3.0 → nocfo_cli-1.4.0}/PKG-INFO +1 -1
  2. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/pyproject.toml +1 -1
  3. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/mcp/http_error_capture.py +18 -8
  4. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/mcp/server.py +1 -0
  5. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/LICENSE +0 -0
  6. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/README.md +0 -0
  7. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/__init__.py +0 -0
  8. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/api_client.py +0 -0
  9. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/__init__.py +0 -0
  10. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/app.py +0 -0
  11. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/__init__.py +0 -0
  12. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/_helpers.py +0 -0
  13. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/accounts.py +0 -0
  14. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/auth.py +0 -0
  15. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/businesses.py +0 -0
  16. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/contacts.py +0 -0
  17. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/documents.py +0 -0
  18. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/files.py +0 -0
  19. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/invoices.py +0 -0
  20. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/products.py +0 -0
  21. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/purchase_invoices.py +0 -0
  22. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/reports.py +0 -0
  23. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/schema.py +0 -0
  24. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/tags.py +0 -0
  25. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/commands/user.py +0 -0
  26. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/context.py +0 -0
  27. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/cli/output.py +0 -0
  28. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/config.py +0 -0
  29. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/mcp/__init__.py +0 -0
  30. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/mcp/auth.py +0 -0
  31. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/mcp/contract_validation.py +0 -0
  32. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/mcp/error_handling.py +0 -0
  33. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/src/nocfo_toolkit/mcp/middleware.py +0 -0
  34. {nocfo_cli-1.3.0 → nocfo_cli-1.4.0}/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.3.0
3
+ Version: 1.4.0
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.3.0"
7
+ version = "1.4.0"
8
8
  description = "NoCFO CLI, MCP server, and Cursor skill toolkit."
9
9
  authors = ["NoCFO"]
10
10
  readme = "README.md"
@@ -21,21 +21,31 @@ def get_last_http_error() -> dict[str, Any] | None:
21
21
 
22
22
 
23
23
  async def capture_http_error_response(response: httpx.Response) -> None:
24
- """Store status/payload for the latest non-success HTTP response."""
24
+ """Store status/payload for the latest HTTP response.
25
25
 
26
- if response.status_code < 400:
27
- _LAST_HTTP_ERROR.set(None)
28
- return
26
+ FastMCP can issue downstream requests with streaming enabled. In that mode,
27
+ accessing ``response.content``/``response.json`` without ``aread()`` raises
28
+ ``ResponseNotRead``. We therefore always drain the body first, even for
29
+ success responses, so tool handlers can safely decode the payload.
30
+ """
29
31
 
30
32
  try:
31
33
  await response.aread()
32
- except httpx.HTTPError:
33
- pass
34
+ except (httpx.HTTPError, httpx.StreamError):
35
+ # Keep best-effort behavior: failures here should not shadow the original
36
+ # tool error path. The middleware still clears stale captured state below.
37
+ _LAST_HTTP_ERROR.set(None)
38
+ return
39
+
40
+ if response.status_code < 400:
41
+ _LAST_HTTP_ERROR.set(None)
42
+ return
34
43
 
35
44
  try:
36
45
  payload: Any = response.json() if response.content else None
37
- except (ValueError, httpx.ResponseNotRead):
38
- payload = (response.text or "").strip()[:1000] or None
46
+ except ValueError:
47
+ text = response.text.strip()
48
+ payload = text[:1000] if text else None
39
49
 
40
50
  _LAST_HTTP_ERROR.set(
41
51
  {
@@ -200,6 +200,7 @@ def create_server(
200
200
  from fastmcp import FastMCP
201
201
 
202
202
  opts = options or MCPServerOptions()
203
+
203
204
  if opts.auth_mode == "oauth":
204
205
  client = _create_oauth_client(
205
206
  config,
File without changes
File without changes