-
Notifications
You must be signed in to change notification settings - Fork 0
Add merchant management tools (get_merchant, list_merchants, update_merchant) #4
Description
Summary
We have UPDATE_MERCHANT_MUTATION in queries.py but it's only used indirectly through update_recurring, which requires an existing stream_id. There's no way to:
- List merchants (with optional name filter)
- Get a single merchant by ID
- Update a merchant's name or recurring settings directly
This blocks the bill-check workflow when we need to find a merchant, create a recurring stream, or rename a merchant in place.
Proposed Tools
list_merchants(name_contains=None)
List all merchants. Optional name_contains filter narrows results (case-insensitive substring match). Returns canonical merchant representation:
{
"id": "...",
"name": "Acme Corp",
"recurring": {
"frequency": "monthly",
"amount": -661.10,
"starting": "2026-01-09",
"status": "active"
}
}Where recurring is null if the merchant has no recurring stream.
get_merchant(merchant_id)
Get a single merchant by ID. Same output shape as list_merchants items.
update_merchant(merchant_id, name=None, recurring=None)
PATCH semantics — only provided fields are updated.
Example 1: Make a merchant recurring for the first time
The merchant exists but has never been flagged as recurring. This should create a new recurring stream that appears in list_recurring.
update_merchant("merchant_id", recurring={
"frequency": "monthly",
"amount": -500.00,
"starting": "2026-01-09",
"status": "active"
})Example 2: Make a merchant non-recurring (remove from recurring entirely)
The merchant currently has a recurring stream. This should remove it from list_recurring permanently. The merchant still exists, it just won't appear as a recurring obligation anymore.
update_merchant("merchant_id", recurring=False)Example 3: Cancel/deactivate a recurring stream (keep but mark inactive)
The merchant stays in the recurring system but is marked canceled. Useful for obligations that ended but you want to keep the history.
update_merchant("merchant_id", recurring={"status": "canceled"})Example 4: Update just the amount for existing recurring
The merchant is already recurring. Only the amount changes — frequency, start date, and status are preserved.
update_merchant("merchant_id", recurring={"amount": -700.00})Example 5: Rename a merchant
update_merchant("merchant_id", name="New Merchant Name")Example 6: Rename and set up recurring in one call
update_merchant("merchant_id", name="New Name", recurring={
"frequency": "monthly",
"amount": -500.00,
"starting": "2026-01-09",
"status": "active"
})Tool Documentation Requirements
update_merchant tool description must:
- Explicitly state that setting
recurringon a merchant creates or updates the recurring stream visible inlist_recurring - Document each example above (first-time recurring, remove recurring, cancel, update amount, rename)
- Clarify the difference between removing recurring (
recurring=False) vs canceling (recurring={"status": "canceled"}) - Note PATCH semantics: only provided keys in the
recurringobject are changed; omitted keys are preserved
list_recurring tool description must:
- Reference
update_merchantas the way to add, modify, or remove recurring streams - State: "To add a new recurring obligation, find the merchant via
list_merchants, then useupdate_merchantto flag it as recurring" - State: "To deactivate or remove a recurring stream, use
update_merchantwith the merchant ID (available in each stream's data)"
This cross-referencing is critical for AI agents to discover the right tool for the job.
Testing Required — Verify Before Documenting
IMPORTANT: The crossover behavior between UPDATE_MERCHANT_MUTATION and the recurring streams list has NOT been fully verified via live API testing. Before committing changes — especially tool documentation that makes claims about behavior — the following must be tested against the live Monarch API:
What we know (from existing docs and code)
From RECURRING.md:
- "Items are transaction-seeded — cannot create from thin air without a transaction" (line 102)
- "Each merchant can only have one recurring stream" (line 103)
- Open question #10: "What mutation fires when adding a recurring merchant?" — never answered
- "No create or delete mutations have been found in any community library" (line 109)
From the memory reference:
- "Create via merchant — UI only — no known GraphQL mutation for setting recurring flag on merchant"
From the codebase:
UPDATE_MERCHANT_MUTATIONexists and accepts a recurrence object (isRecurring,frequency,amount,baseDate,isActive)update_recurringalready uses this mutation successfully to modify existing streams
What must be verified
| Test | Question | Impact on documentation |
|---|---|---|
| Create recurring via mutation | Does calling UPDATE_MERCHANT_MUTATION with isRecurring: True on a merchant with NO existing stream actually create a new stream in list_recurring? |
If no, Example 1 is wrong and we need a different approach |
| Remove recurring via mutation | Does setting isRecurring: False remove the stream from list_recurring? Or do we need Common_MarkAsNotRecurring? |
Affects Example 2 |
| Cancel vs remove | Does isActive: False keep the stream visible but inactive, vs isRecurring: False removing it entirely? |
Affects distinction between Examples 2 and 3 |
| Transaction-seeded requirement | Can we create a recurring stream for a merchant that has transactions but was never auto-detected? (Our use case — renamed payment merchants) | Core use case viability |
| Idempotency | Is calling the mutation on an already-recurring merchant safe? Does it preserve existing stream data for omitted fields? | Affects PATCH semantics claims |
Recommended approach
- Implement the tool with the proposed interface
- Write integration tests that exercise each scenario above against the live API
- Only after tests pass, update the tool documentation with confirmed behavior
- Update
RECURRING.mdwith answers to open question #10 and the verified behavior
Do NOT document crossover behavior (e.g., "this creates a recurring stream") as fact until verified by test.
GraphQL Queries Available
Both queries are already defined in queries.py:
MERCHANT_SEARCH_QUERY # Search merchants by name, returns recurring stream info
GET_MERCHANT_QUERY # Get single merchant by ID with transaction count, rule count, recurring
UPDATE_MERCHANT_MUTATION # Update name and/or recurrence settingsImplementation Notes
- The recurrence input maps:
isRecurring→ recurring presence,frequency→ frequency,amount→ amount,baseDate→ starting,isActive→ status (active/canceled) update_recurringinrecurring.pyalready builds the mutation variables — refactor to share logic- Consider deprecating
update_recurringin favor ofupdate_merchant(or make it a thin wrapper) - Expose
merchant_idinlist_recurringoutput if not already present
Related
- Issue Merchant logo management and split-merchant workflow documentation #3 — parent tracking issue (merchant management section now covered here)
- Issue Recurring stream retrieval misses liability streams, newly created merchants, and pending items — switch to aggregated query #5 —
list_recurringimprovements (cross-reference in tool docs) - Issue Add transaction rule management tools (list_rules, create_rule, delete_rule) #6 — Transaction rule tools (rules reference merchants)