modern-collections
The official Python client, command-line tool and MCP server for the Modern Collections API. With a Modern Collections API key you, a script, or your AI assistant can do what you do in the creditor dashboard: place overdue invoices, find and follow accounts, record payments, work disputes, attach documents, and pull what has been collected.
- AI assistants (Claude, Cursor, anything that speaks MCP) connect to the
hosted server at
https://api.moderncollections.io/mcp. No install. - Command line:
modern-collections. - Python:
from mc_api import MCClient.
Connect your AI assistant
No install: the hosted server
Point any MCP client that can send a custom header at:
- URL:
https://api.moderncollections.io/mcp(streamable HTTP) - Header:
Authorization: Bearer <your API key>
{
"mcpServers": {
"modern-collections": {
"url": "https://api.moderncollections.io/mcp",
"headers": { "Authorization": "Bearer ca_..." }
}
}
}
Then ask your assistant to run account_whoami. It names the account the key
reaches and says what, if anything, blocks placing (verification, the
agreement, the payout account).
One command: Claude Code, Cursor, Claude Desktop
uv tool install modern-collections # or: pip install modern-collections
modern-collections mcp install --client claude-code # or cursor, claude-desktop
It asks for your key without echoing it, checks it, and only then writes the client's configuration:
--client |
What it writes |
|---|---|
claude-code |
runs claude mcp add --transport http against the hosted server (--scope user by default) |
cursor |
~/.cursor/mcp.json |
claude-desktop |
Claude Desktop's config file: a local modern-collections-mcp entry, or with --transport remote the hosted server through npx mcp-remote |
Other servers already in those files are left alone. Restart Claude Desktop after installing.
Local server
The same tools run as a local stdio server, with the key in its environment:
MC_API_ENV=prod MC_API_KEY=ca_... modern-collections-mcp
modern-collections-mcp --http serves the same thing over streamable HTTP on
http://127.0.0.1:8765/mcp; the key then comes from each request's
Authorization header.
Getting a key
Dashboard → Settings → API Key. The key is shown once, when it is created or rotated; Modern Collections keeps only a one-way hash, so a lost key is rotated, not recovered. Setup snippets are under Settings → Developer access.
Creditor keys look like ca_<prefix>_<secret>. Partner keys (pa_<prefix>_<secret>)
act for every creditor linked to the partner; see Partner keys.
What your assistant can do
A default set of about 25 tools covers everyday work:
| Area | Tools |
|---|---|
| Setup | account_whoami, guide, partner_creditor_list |
| Placing and following | placement_create, placement_list (search by company or invoice number), placement_status, audit_query, placement_context |
| Changing a placement | placement_amend, placement_update_debtor, placement_set_posture, placement_recall |
| Payments | payment_record, payment_list |
| Disputes | dispute_list, dispute_get, dispute_acknowledge, dispute_resolve |
| Documents | document_upload, document_upload_link, placement_documents, document_status |
| Reporting | analytics_summary, analytics_series, remittance_list, statement_list, statement_download_url |
Everything else (settlement floors, contact choices, CSV and file intake,
evidence scoring, the recovery workspace, notifications, webhooks, QuickBooks)
is in the full set. Turn it on with ?tools=all on the hosted URL (or the
header X-MC-Tools: all), MC_API_MCP_TOOLS=all for the local server, or
--all-tools on mcp install.
document_upload_link is for files on your computer that a chat assistant
cannot read: it returns a link, valid for 30 minutes, that you open in a
browser to upload the file onto the placement.
Confirmations
Tools that contact a debtor, move money, change who is contacted, or make a
legal statement are marked destructive (placement_create, payment_record,
placement_amend, placement_update_debtor, dispute_resolve,
placement_recall, intake commits, and a few more). Your assistant asks before
using them, and most MCP clients ask you too. When you want your assistant to
act without asking, tell it so, or choose "always allow" for those tools in
your MCP client.
placement_create starts real outreach to a real company. There is no sandbox
on this API; placement_recall stops a placement that should not have been
opened.
Install
uv tool install modern-collections # CLI + local MCP server
pip install modern-collections # or as a library
Python 3.11 or later. The PyPI project named mc-api is unrelated.
Configure
Pick an environment and supply a key. There is no default environment, so a
forgotten setting can never send a key to the wrong place. The key is read
from MC_API_KEY and is never printed or logged.
| Variable | Values |
|---|---|
MC_API_ENV |
prod or demo |
MC_API_BASE_URL |
an explicit API URL (overrides MC_API_ENV) |
MC_API_KEY |
ca_... (creditor) or pa_... (partner) |
MC_API_CREDITOR |
partner keys only: the default creditor to act for |
Command line
export MC_API_ENV=prod MC_API_KEY=ca_...
modern-collections whoami # check your setup
modern-collections placements list --q "Acme" # find by company or invoice number
modern-collections placements create --company "Acme Freight" --amount 7500.00 --email ap@acme.co \
--invoice-number INV-4411 --invoice-date 2026-01-01 --due-date 2026-02-01 --state OH
modern-collections placements get <placement_id>
modern-collections placements audit <placement_id> # what has happened on the account
modern-collections payments record <placement_id> --amount 500.00 --idempotency-key <bank-ref>
modern-collections disputes list --status open
modern-collections documents upload invoice-4411.pdf --placement <placement_id> --type invoice
modern-collections documents upload-link <placement_id> --type invoice
modern-collections analytics summary
modern-collections remittances list
-o json gives machine-readable output. It is a global option, so it goes
before the subcommand (modern-collections -o json placements list), as do
--env, --base-url, --api-key, --creditor and --timeout. Exit codes:
0 success, 1 API or runtime error, 2 configuration or usage error.
File an invoice, read it back, correct it
P=$(modern-collections -o json placements create --company "Acme Freight" --amount 7500.00 \
--invoice-number INV-4411 --invoice-date 2026-01-01 --due-date 2026-02-01 \
| jq -r .placement_id)
modern-collections documents upload invoice-4411.pdf --placement $P --type invoice
modern-collections placements context $P # what was read off the invoice
modern-collections placements amend $P --po-number PO-8871 --reason "read off the signed BOL"
modern-collections placements amend $P --amount 7250.00 --reason "credit memo applied"
modern-collections placements debtor $P --email ap@acmefreight.com
Amendments apply while outreach is running: the next call or email uses the
corrected placement. Every edit is kept as an append-only, audited record. One
amendment kind per call: --amount, --notes/--clear-notes, or any mix of
the invoice fields (--invoice-number, --invoice-date, --due-date,
--po-number, --service-date, --currency, --written-contract). Status is
changed through payments record, disputes resolve or placements recall.
Python
from mc_api import MCClient, NotFoundError
with MCClient(env="prod", api_key="ca_...") as api:
print(api.whoami()["blocking"])
placement = api.create_placement(
{
"invoice_amount": "7500.00",
"invoice_number": "INV-4411",
"invoice_date": "2026-01-01",
"due_date": "2026-02-01",
"debtor": {"company_name": "Acme Freight", "primary_email": "ap@acme.co"},
},
idempotency_key="INV-4411",
)
for row in api.iter_placements(q="Acme", status="in_outreach"):
print(row["id"], row["invoice_amount"])
try:
api.get_placement("00000000-0000-0000-0000-000000000000")
except NotFoundError:
pass
Errors are ApiError subclasses: AuthError (401/403), NotFoundError,
ValidationError (400/422, with field errors flattened to one line) and
RateLimitedError (429, with retry_after). iter_placements,
iter_documents, iter_payments, iter_remittances, iter_statements,
iter_exports, iter_audit and iter_partner_creditors walk every page lazily.
The package ships type hints (py.typed).
Partner keys
A partner key reaches every creditor linked to the partner through one connection, one creditor per call:
- MCP: run
partner_creditor_list, then passcreditor=on each call (the creditor's id, its external reference, or its exact name). - CLI:
modern-collections partner creditors, then--creditor <id or ref>, or setMC_API_CREDITOR. - Python:
MCClient(api_key="pa_...", creditor="<id or ref>").
A call without a creditor gets a 400 from the API; the client never guesses.
With a creditor key the creditor argument is ignored.
Agent skills
Two skills teach an assistant how to work the account: modern-collections
(everyday operations) and collections-ar-triage (turn an AR aging export into a
reviewed batch of placements). They ship in this package:
modern-collections skills install # into ~/.claude/skills
modern-collections skills install --dir <project>/.claude/skills
Over MCP the same text is available as prompts, as resources
(modern-collections://skills/<name>), and through the guide tool.
Kept out of reach on purpose
- Accepting the master service agreement is a person's click in the dashboard. The API refuses it from an API key, and no tool or command offers it.
- Rotating the API key and setting the webhook URL need a signed-in dashboard session, so a leaked key cannot replace itself or redirect events.
- Signing secrets stay out of the model. The intake webhook secret can be rotated and used from the CLI and the Python client, not through MCP.
Safety properties
- The API key lives only in the request
Authorizationheader. It is kept out ofrepr(), exceptions and logs, and so is the creditor scope; neither is sent on the unauthenticatedhealth()check. - Explicit connect, read and write timeouts.
- Reads are retried on 429 (honouring
Retry-After), 502, 503 and 504. A write is retried only when it carries an idempotency key, which the server replays; other writes are sent once, so a create or a payment is never silently duplicated. The MCP server derives a key forplacement_createandpayment_recordwhen none is given, so a retried tool call replays instead of acting twice. - Client-side checks on amendment fields and enum-like arguments, so a typo fails locally.
- Signed structured intake is HMAC'd over the exact bytes sent.
License
Apache License 2.0. See LICENSE.
Metadata
Release files for modern-collections 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| modern_collections-0.2.0.tar.gz | 87.7 kB | Without provenance | Details for modern_collections-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| modern_collections-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for modern_collections-0.2.0-py3-none-any.whl |
Total release size: 182.3 kB
Release files / modern_collections-0.2.0.tar.gz
| Download URL | modern_collections-0.2.0.tar.gz |
|---|---|
| Size | 87.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bca085e7faa8da7252a4a2b975672d9e9c5759a4444be198c91253c5192aaeab
|
|
BLAKE2b-256 checksum How to use checksums |
2e3f3cab8618ee540d6e9026e83a80a3eca66b10b6aa1abb96cc78843c51912f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.8 {"installer":{"name":"uv","version":"0.12.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / modern_collections-0.2.0-py3-none-any.whl
| Download URL | modern_collections-0.2.0-py3-none-any.whl |
|---|---|
| Size | 94.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
becb4c5385c9d165b1d01c2697d0ca3b4e3a1c2107332f2c95da339785d69f83
|
|
BLAKE2b-256 checksum How to use checksums |
eeb8be7df75fc830029afbfe6f5b44c4b123d31ac0bd0064c1a195f48e8c420d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.8 {"installer":{"name":"uv","version":"0.12.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for modern-collections 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.