calculate_reimbursements
Quickly compute reimbursement amounts for a gathering by entering the event ID to settle balances between participants efficiently.
Instructions
Calculate reimbursements for a gathering
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| gathering_id | Yes | ID of the gathering |
Implementation Reference
- services.py:67-96 (handler)Core handler function implementing the reimbursement calculation logic for the MCP tool. Computes the net amount each member owes or is owed based on shared expenses and recorded payments.def calculate_reimbursements(self, gathering_id: str) -> Dict[str, float]: """ Calculate reimbursements for a gathering. Args: gathering_id: The ID of the gathering Returns: A dictionary mapping member names to reimbursement amounts (negative values mean the member gets reimbursed, positive values mean they owe money) Raises: ValueError: If the gathering doesn't exist """ gathering = self.get_gathering(gathering_id) if not gathering: raise ValueError(f"Gathering '{gathering_id}' not found") # Calculate how much each member has paid and should pay expense_per_member = gathering.expense_per_member # Calculate reimbursements reimbursements = {} for member in gathering.members: # Amount to pay = total share - expenses + payments # If negative, member gets reimbursed; if positive, member owes money to_pay = expense_per_member - member.total_expenses + member.total_payments reimbursements[member.name] = to_pay return reimbursements
- src/index.ts:104-117 (schema)MCP tool schema definition, including the input schema that validates the required 'gathering_id' parameter.{ name: 'calculate_reimbursements', description: 'Calculate reimbursements for a gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering', }, }, required: ['gathering_id'], }, },
- src/index.ts:62-254 (registration)Registration of the calculate_reimbursements tool in the MCP server's ListToolsRequestSchema handler, which advertises available tools to clients.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'create_gathering', description: 'Create a new gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'Unique ID for the gathering (format: yyyy-mm-dd-type)', }, members: { type: 'number', description: 'Number of members in the gathering', }, }, required: ['gathering_id', 'members'], }, }, { name: 'add_expense', description: 'Add an expense for a member', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering', }, member_name: { type: 'string', description: 'Name of the member who paid', }, amount: { type: 'number', description: 'Amount paid by the member', }, }, required: ['gathering_id', 'member_name', 'amount'], }, }, { name: 'calculate_reimbursements', description: 'Calculate reimbursements for a gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering', }, }, required: ['gathering_id'], }, }, { name: 'record_payment', description: 'Record a payment made by a member', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering', }, member_name: { type: 'string', description: 'Name of the member making the payment', }, amount: { type: 'number', description: 'Amount paid (negative for reimbursements)', }, }, required: ['gathering_id', 'member_name', 'amount'], }, }, { name: 'rename_member', description: 'Rename an unnamed member', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering', }, old_name: { type: 'string', description: 'Current name of the member', }, new_name: { type: 'string', description: 'New name for the member', }, }, required: ['gathering_id', 'old_name', 'new_name'], }, }, { name: 'show_gathering', description: 'Show details of a gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering to display', }, }, required: ['gathering_id'], }, }, { name: 'list_gatherings', description: 'List all gatherings', inputSchema: { type: 'object', properties: {}, }, }, { name: 'close_gathering', description: 'Close a gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering to close', }, }, required: ['gathering_id'], }, }, { name: 'delete_gathering', description: 'Delete a gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering to delete', }, force: { type: 'boolean', description: 'Force deletion even if gathering is closed', default: false, }, }, required: ['gathering_id'], }, }, { name: 'add_member', description: 'Add a new member to a gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering', }, member_name: { type: 'string', description: 'Name of the member to add', }, }, required: ['gathering_id', 'member_name'], }, }, { name: 'remove_member', description: 'Remove a member from a gathering', inputSchema: { type: 'object', properties: { gathering_id: { type: 'string', description: 'ID of the gathering', }, member_name: { type: 'string', description: 'Name of the member to remove', }, }, required: ['gathering_id', 'member_name'], }, }, ], }));
- src/index.ts:309-314 (handler)MCP CallToolRequestSchema handler case that validates arguments and constructs the CLI command to invoke the Python implementation.case 'calculate_reimbursements': if (!isGatheringIdArg(args)) { throw new McpError(ErrorCode.InvalidParams, 'Invalid calculate_reimbursements arguments'); } command += ` calculate "${args.gathering_id}"`; break;
- gatherings.py:144-180 (helper)CLI handler for the 'calculate' subcommand that calls the service method and formats the JSON or text output for the MCP server.def handle_calculate(service, args): """Handle the calculate command.""" try: reimbursements = service.calculate_reimbursements(args.gathering_id) gathering = service.get_gathering(args.gathering_id) result = { "success": True, "calculation": { "total_expenses": gathering.total_expenses, "expense_per_member": gathering.expense_per_member, "reimbursements": { name: {"amount": amount, "type": "gets_reimbursed" if amount < 0 else "needs_to_pay"} for name, amount in reimbursements.items() } } } if args.json: print(json.dumps(result)) else: print(f"Total expenses: ${gathering.total_expenses:.2f}") print(f"Expense per member: ${gathering.expense_per_member:.2f}") print("Reimbursements:") for name, amount in reimbursements.items(): if amount < 0: print(f" {name} gets reimbursed ${abs(amount):.2f}") else: print(f" {name} needs to pay ${amount:.2f}") return True except ValueError as e: error = {"success": False, "error": str(e)} if args.json: print(json.dumps(error)) else: print(f"Error: {e}") return False