lambda-erp 1.1.3__tar.gz → 1.1.4__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 (113) hide show
  1. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/PKG-INFO +1 -1
  2. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/mcp.py +15 -4
  3. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/pyproject.toml +1 -1
  4. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/.gitignore +0 -0
  5. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/LICENSE +0 -0
  6. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/README.md +0 -0
  7. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/__init__.py +0 -0
  8. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/attachments.py +0 -0
  9. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/auth.py +0 -0
  10. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/bootstrap.py +0 -0
  11. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/chat.py +0 -0
  12. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/chat_links.py +0 -0
  13. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/demo_limits.py +0 -0
  14. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/deps.py +0 -0
  15. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/errors.py +0 -0
  16. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/list_values.py +0 -0
  17. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/main.py +0 -0
  18. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/mcp_oauth.py +0 -0
  19. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/oauth.py +0 -0
  20. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/pdf.py +0 -0
  21. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/pdf_contract.py +0 -0
  22. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/pdf_exports.py +0 -0
  23. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/pdf_profiles.py +0 -0
  24. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/providers.py +0 -0
  25. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/remarks_md.py +0 -0
  26. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/__init__.py +0 -0
  27. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/accounting.py +0 -0
  28. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/actions.py +0 -0
  29. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/admin.py +0 -0
  30. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/analytics.py +0 -0
  31. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/availability.py +0 -0
  32. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/bank_reconciliation.py +0 -0
  33. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/bank_statements.py +0 -0
  34. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/chat_api.py +0 -0
  35. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/documents.py +0 -0
  36. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/masters.py +0 -0
  37. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/proposals.py +0 -0
  38. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/reports.py +0 -0
  39. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/routers/setup.py +0 -0
  40. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/services.py +0 -0
  41. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/templates/_proposal_totals.html +0 -0
  42. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/templates/_record_base.html +0 -0
  43. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/templates/document.html +0 -0
  44. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/templates/proposal.html +0 -0
  45. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/templates/record.html +0 -0
  46. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/time_filters.py +0 -0
  47. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/api/tool_permissions.py +0 -0
  48. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/docs/agents/README.md +0 -0
  49. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/frontend/LICENSE +0 -0
  50. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/frontend/README.md +0 -0
  51. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/frontend/src/api/client.ts +0 -0
  52. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/__init__.py +0 -0
  53. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/__init__.py +0 -0
  54. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/bank_account.py +0 -0
  55. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/bank_reconciliation.py +0 -0
  56. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/bank_statement_import.py +0 -0
  57. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/bank_transaction.py +0 -0
  58. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/budget.py +0 -0
  59. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/camt.py +0 -0
  60. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/chart_of_accounts.py +0 -0
  61. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/general_ledger.py +0 -0
  62. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/journal_entry.py +0 -0
  63. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/payment_entry.py +0 -0
  64. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/pos_invoice.py +0 -0
  65. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/purchase_invoice.py +0 -0
  66. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/revaluation.py +0 -0
  67. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/sales_invoice.py +0 -0
  68. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/settlement.py +0 -0
  69. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/__init__.py +0 -0
  70. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/engine.py +0 -0
  71. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/pack.py +0 -0
  72. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/packs/__init__.py +0 -0
  73. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/packs/ch.py +0 -0
  74. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/packs/de_common.py +0 -0
  75. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/packs/de_skr03.py +0 -0
  76. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/packs/de_skr04.py +0 -0
  77. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/packs/generic.py +0 -0
  78. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/profiles.py +0 -0
  79. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/setup/spine.py +0 -0
  80. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/accounting/subscription.py +0 -0
  81. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/assets/__init__.py +0 -0
  82. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/assets/asset.py +0 -0
  83. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/assets/lifecycle.py +0 -0
  84. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/assets/reservation.py +0 -0
  85. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/buying/__init__.py +0 -0
  86. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/buying/purchase_order.py +0 -0
  87. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/controllers/__init__.py +0 -0
  88. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/controllers/currency.py +0 -0
  89. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/controllers/defaults.py +0 -0
  90. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/controllers/item_price.py +0 -0
  91. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/controllers/item_prices.py +0 -0
  92. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/controllers/pricing_rule.py +0 -0
  93. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/controllers/taxes_and_totals.py +0 -0
  94. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/database.py +0 -0
  95. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/exceptions.py +0 -0
  96. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/hooks.py +0 -0
  97. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/master_integrity.py +0 -0
  98. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/model.py +0 -0
  99. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/selling/__init__.py +0 -0
  100. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/selling/proposal.py +0 -0
  101. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/selling/quotation.py +0 -0
  102. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/selling/sales_order.py +0 -0
  103. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/simulation.py +0 -0
  104. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/stock/__init__.py +0 -0
  105. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/stock/delivery_note.py +0 -0
  106. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/stock/purchase_receipt.py +0 -0
  107. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/stock/stock_entry.py +0 -0
  108. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/stock/stock_ledger.py +0 -0
  109. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/timestamps.py +0 -0
  110. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/utils.py +0 -0
  111. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/validation.py +0 -0
  112. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/lambda_erp/workflow.py +0 -0
  113. {lambda_erp-1.1.3 → lambda_erp-1.1.4}/terraform/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: lambda-erp
3
- Version: 1.1.3
3
+ Version: 1.1.4
4
4
  Summary: Core ERP logic - accounting, sales, purchasing, inventory
5
5
  Author: TORUS INVESTMENTS AG
6
6
  License-Expression: Apache-2.0
@@ -33,6 +33,7 @@ from api.tool_permissions import tool_allowed
33
33
  router = APIRouter(tags=["mcp"])
34
34
 
35
35
  PROTOCOL_VERSION = "2025-06-18"
36
+ SUPPORTED_PROTOCOL_VERSIONS = frozenset({'2025-03-26', PROTOCOL_VERSION})
36
37
 
37
38
  # Chat-session-only tools have no meaning without a chat session — keep them out
38
39
  # of the MCP surface (an MCP client owns its own context).
@@ -158,8 +159,12 @@ def _handle(msg: dict, user: dict):
158
159
  return None if is_notification else {"jsonrpc": "2.0", "id": mid, "result": payload}
159
160
 
160
161
  if method == "initialize":
162
+ requested_version = (msg.get('params') or {}).get('protocolVersion', PROTOCOL_VERSION)
163
+ if not isinstance(requested_version, str):
164
+ return _rpc_error(mid, -32602, 'Expected a string protocolVersion')
161
165
  return result({
162
- "protocolVersion": PROTOCOL_VERSION,
166
+ "protocolVersion": (requested_version if requested_version in SUPPORTED_PROTOCOL_VERSIONS
167
+ else PROTOCOL_VERSION),
163
168
  "capabilities": {"tools": {"listChanged": False}},
164
169
  "serverInfo": {"name": "lambda-erp", "version": get_app_version()},
165
170
  })
@@ -194,9 +199,9 @@ async def mcp_endpoint(request: Request):
194
199
  allowed_origins = {issuer(request), *os.environ.get('MCP_ALLOWED_ORIGINS', '').split(',')}
195
200
  if origin and origin not in allowed_origins:
196
201
  raise HTTPException(403, 'Invalid Origin')
197
- version = request.headers.get('mcp-protocol-version')
198
- if version and version not in {'2025-03-26', PROTOCOL_VERSION}:
199
- raise HTTPException(400, 'Unsupported MCP protocol version')
202
+ # Authentication discovery must work before the client has negotiated an
203
+ # MCP version. Otherwise a newer connector gets 400 instead of the 401
204
+ # challenge that tells it how to sign in.
200
205
  user = _require_caller(request)
201
206
  try:
202
207
  body = await request.json()
@@ -206,6 +211,12 @@ async def mcp_endpoint(request: Request):
206
211
  # Keep legacy batch support, but reject malformed messages rather than 500.
207
212
  if not isinstance(body, (dict, list)) or (isinstance(body, list) and (not body or any(not isinstance(m, dict) for m in body))):
208
213
  return JSONResponse(_rpc_error(None, -32600, "Invalid Request"), status_code=400)
214
+ # initialize negotiates the revision in its JSON-RPC payload. The version
215
+ # header is enforced on subsequent calls, after the client has our answer.
216
+ initializing = isinstance(body, dict) and body.get('method') == 'initialize'
217
+ version = request.headers.get('mcp-protocol-version')
218
+ if not initializing and version and version not in SUPPORTED_PROTOCOL_VERSIONS:
219
+ raise HTTPException(400, 'Unsupported MCP protocol version')
209
220
  if isinstance(body, list):
210
221
  responses = [r for r in (_handle(m, user) for m in body) if r is not None]
211
222
  return JSONResponse(responses) if responses else Response(status_code=202)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lambda-erp"
3
- version = "1.1.3"
3
+ version = "1.1.4"
4
4
  description = "Core ERP logic - accounting, sales, purchasing, inventory"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
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