Ver Fonte

Add MCP server, maybe

ZiB há 5 meses atrás
pai
commit
07c79962e2
2 ficheiros alterados com 180 adições e 0 exclusões
  1. 179 0
      mcp_server.py
  2. 1 0
      requirements.txt

+ 179 - 0
mcp_server.py

@@ -0,0 +1,179 @@
+import json
+import os
+from mcp.server.fastmcp import FastMCP
+
+_here = os.path.dirname(__file__)
+
+with open(os.path.join(_here, "config.json")) as f:
+  _config = json.load(f)
+
+SERVICES = _config['services']
+SALES_TAX = _config['global']['taxes']['sales']
+
+mcp = FastMCP("room-price-calc")
+
+def _dollar(v: float) -> str:
+  return "{:.2f}".format(round(v, 2))
+
+def _details_fmt(details: dict) -> dict:
+  return {k.replace('_', ' ').title(): _dollar(v) for k, v in details.items()}
+
+def _resolve_service(service: str):
+  svc = SERVICES.get(service.lower().strip())
+  if svc is None:
+    keys = ', '.join(SERVICES.keys())
+    raise ValueError(f"Unknown service '{service}'. Valid keys: {keys}")
+  return svc
+
+def _n2l(svc, net, det):
+  comm_rate = svc.get('fees', {}).get('commission', 0)
+  wrong_rate = svc.get('taxes', {}).get('wrong', SALES_TAX)
+  list_ = net / (1 - comm_rate - SALES_TAX + wrong_rate)
+  if 'fees' in svc and 'commission' in svc['fees']:
+    det['commission'] = list_ * comm_rate
+  if 'taxes' in svc and 'wrong' in svc['taxes']:
+    det['wrong_tax'] = list_ * wrong_rate
+    det['sales_tax'] = list_ * SALES_TAX
+    det['wrong_tax_loss'] = det['sales_tax'] - det['wrong_tax']
+  return round(list_, 2)
+
+def _l2n(svc, list_, det):
+  net = list_
+  if 'fees' in svc and 'commission' in svc['fees']:
+    det['commission'] = net * svc['fees']['commission']
+  if 'taxes' in svc and 'wrong' in svc['taxes']:
+    det['sales_tax'] = net * SALES_TAX
+    det['wrong_tax'] = net * svc['taxes']['wrong']
+    det['wrong_tax_loss'] = det['sales_tax'] - det['wrong_tax']
+  for k in ['commission', 'wrong_tax_loss']:
+    if k in det:
+      net -= det[k]
+  return round(net, 2)
+
+def _l2r(svc, list_, det):
+  retail = list_
+  if 'fees' in svc and 'client_fee' in svc['fees']:
+    det['client_fee'] = retail * svc['fees']['client_fee']
+    retail += det['client_fee']
+  if 'taxes' in svc and 'wrong' in svc['taxes']:
+    det['wrong_tax'] = retail * svc['taxes']['wrong']
+    retail += det['wrong_tax']
+  else:
+    det['sales_tax'] = retail * SALES_TAX
+    retail += det['sales_tax']
+  if 'taxes' in svc and 'flat_tax' in svc['taxes']:
+    det['service_tax'] = svc['taxes']['flat_tax']
+    retail += det['service_tax']
+  return round(retail, 2)
+
+def _r2l(svc, retail, det):
+  list_ = retail
+  if 'taxes' in svc and 'flat_tax' in svc['taxes']:
+    det['service_tax'] = svc['taxes']['flat_tax']
+    list_ -= det['service_tax']
+  if 'taxes' in svc and 'wrong' in svc['taxes']:
+    det['wrong_tax'] = list_ - (list_ / (1 + svc['taxes']['wrong']))
+    list_ -= det['wrong_tax']
+  else:
+    det['sales_tax'] = list_ - (list_ / (1 + SALES_TAX))
+    list_ -= det['sales_tax']
+  if 'fees' in svc and 'client_fee' in svc['fees']:
+    det['client_fee'] = list_ - (list_ / (1 + svc['fees']['client_fee']))
+    list_ -= det['client_fee']
+  return round(list_, 2)
+
+def _result(service_key, **amounts) -> dict:
+  det = {k: _dollar(v) for k, v in amounts.items() if k != 'details'}
+  return {'service': service_key, **det}
+
+@mcp.tool()
+def list_services() -> list:
+  """List all available booking services with their keys and display names."""
+  return [{'key': k, 'name': v['name']} for k, v in SERVICES.items()]
+
+@mcp.tool()
+def net_to_list(service: str, amount: float) -> dict:
+  """Convert a net (owner payout) amount to the list (booking) price for a service.
+
+  Args:
+    service: Service key (e.g. 'airbnb', 'booking')
+    amount: Net amount in dollars
+  """
+  svc = _resolve_service(service)
+  det = {}
+  list_ = _n2l(svc, amount, det)
+  return {'service': service, 'net': _dollar(amount), 'list': _dollar(list_), 'details': _details_fmt(det)}
+
+@mcp.tool()
+def list_to_net(service: str, amount: float) -> dict:
+  """Convert a list (booking) price to the net (owner payout) amount for a service.
+
+  Args:
+    service: Service key (e.g. 'airbnb', 'booking')
+    amount: List price in dollars
+  """
+  svc = _resolve_service(service)
+  det = {}
+  net = _l2n(svc, amount, det)
+  return {'service': service, 'list': _dollar(amount), 'net': _dollar(net), 'details': _details_fmt(det)}
+
+@mcp.tool()
+def list_to_retail(service: str, amount: float) -> dict:
+  """Convert a list (booking) price to the retail (guest-facing) price for a service.
+
+  Args:
+    service: Service key (e.g. 'airbnb', 'booking')
+    amount: List price in dollars
+  """
+  svc = _resolve_service(service)
+  det = {}
+  retail = _l2r(svc, amount, det)
+  return {'service': service, 'list': _dollar(amount), 'retail': _dollar(retail), 'details': _details_fmt(det)}
+
+@mcp.tool()
+def retail_to_list(service: str, amount: float) -> dict:
+  """Convert a retail (guest-facing) price to the list (booking) price for a service.
+
+  Args:
+    service: Service key (e.g. 'airbnb', 'booking')
+    amount: Retail price in dollars
+  """
+  svc = _resolve_service(service)
+  det = {}
+  list_ = _r2l(svc, amount, det)
+  return {'service': service, 'retail': _dollar(amount), 'list': _dollar(list_), 'details': _details_fmt(det)}
+
+@mcp.tool()
+def net_to_retail(service: str, amount: float) -> dict:
+  """Convert a net (owner payout) amount to the retail (guest-facing) price for a service.
+
+  Args:
+    service: Service key (e.g. 'airbnb', 'booking')
+    amount: Net amount in dollars
+  """
+  svc = _resolve_service(service)
+  det = {}
+  list_ = _n2l(svc, amount, det)
+  det2 = {}
+  retail = _l2r(svc, list_, det2)
+  det.update(det2)
+  return {'service': service, 'net': _dollar(amount), 'list': _dollar(list_), 'retail': _dollar(retail), 'details': _details_fmt(det)}
+
+@mcp.tool()
+def retail_to_net(service: str, amount: float) -> dict:
+  """Convert a retail (guest-facing) price to the net (owner payout) amount for a service.
+
+  Args:
+    service: Service key (e.g. 'airbnb', 'booking')
+    amount: Retail price in dollars
+  """
+  svc = _resolve_service(service)
+  det = {}
+  list_ = _r2l(svc, amount, det)
+  det2 = {}
+  net = _l2n(svc, list_, det2)
+  det.update(det2)
+  return {'service': service, 'retail': _dollar(amount), 'list': _dollar(list_), 'net': _dollar(net), 'details': _details_fmt(det)}
+
+if __name__ == "__main__":
+  mcp.run()

+ 1 - 0
requirements.txt

@@ -1,2 +1,3 @@
 Flask
 Flask-CORS
+mcp[cli]