MCP server
Let an AI assistant answer questions about your vacancies, criteria and matches, with the same token rules as the API.
The server
- URL:
https://developers.propfit.co/api/mcp. Streamable HTTP, stateless, JSON responses. - Authenticate with an organization API token in an
Authorization: Bearerheader. The assistant sees only the tools the token’s scopes allow. - Every tool calls the same API v1 operation as the REST API: same scopes, same organization boundary, same audit trail and rate limit.
- There are no tools to publish a vacancy, approve, decline or waitlist an applicant, order a background check or read renter details. An assistant can ask an applicant to authorize a background check and read where it stands (pass or needs review).
Connect Claude Code
claude mcp add --transport http propfit https://developers.propfit.co/api/mcp \
--header "Authorization: Bearer $PROPFIT_TOKEN"Connect Cursor
Add the server to ~/.cursor/mcp.json (or .cursor/mcp.json in a project). Keep the token out of files you commit.
{
"mcpServers": {
"propfit": {
"url": "https://developers.propfit.co/api/mcp",
"headers": { "Authorization": "Bearer pf_api_…" }
}
}
}Connect Claude Desktop
Add a custom connector with the URL https://developers.propfit.co/api/mcp and nothing else: Claude signs you in to PropFit with OAuth, you pick the organization and what it may do, and you can disconnect it any time in Settings → Integrations. To use a token instead, connect through the mcp-remote bridge, which sends the token header for you. In Claude Desktop, open Settings → Developer → Edit Config and add:
{
"mcpServers": {
"propfit": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://developers.propfit.co/api/mcp", "--header", "Authorization:${PROPFIT_AUTH}"],
"env": { "PROPFIT_AUTH": "Bearer pf_api_…" }
}
}
}Restart Claude Desktop. Any other client that supports streamable HTTP with custom headers (the MCP Inspector, for one) uses the same URL and header.
Tools
This list is generated from the running server, so it always matches what a client sees.
list_vacancies
List vacancies · scope read:offers · read-only
List the organization’s vacancies (offers) with status, rent, available date, move-in cost, what is missing before publishing, and live qualification links. Filter by status. Paginated: pass next_cursor back as cursor.
| Argument | Type | Description |
|---|---|---|
status | draft | published | paused | leased | withdrawn[] | Only these statuses. Default: all. |
cursor | string | next_cursor from the previous page. |
limit | integer | Page size, 1–100 (default 25). |
get_vacancy
Get a vacancy · scope read:offers · read-only
One vacancy in full: terms, itemized fees, monthly and move-in cost, readiness, the governing criteria policy and link slugs.
| Argument | Type | Description |
|---|---|---|
vacancy_id (required) | string (uuid) | The vacancy (offer) id, from list_vacancies. |
get_criteria
Get a vacancy’s criteria · scope read:criteria · read-only
The qualification criteria that govern a vacancy, in plain words by pathway (any one pathway qualifies), and the compliance-check result recorded when they were activated. Read-only: criteria are changed by a person in the app.
| Argument | Type | Description |
|---|---|---|
vacancy_id (required) | string (uuid) | The vacancy (offer) id, from list_vacancies. |
vacancy_funnel
Vacancy funnel · scope read:analytics · read-only
Aggregate counts for a vacancy: renters shown it, prospects, potential and verified matches, applications, invitations, links by channel. Counts from 1 to 4 come back as null (small groups are hidden to protect renters).
| Argument | Type | Description |
|---|---|---|
vacancy_id (required) | string (uuid) | The vacancy (offer) id, from list_vacancies. |
match_summary
Match summary (assertions only) · scope read:matches · read-only
Without vacancy_id: prospect counts by match state for every published or paused vacancy. With vacancy_id: counts plus, per renter who engaged with that vacancy, a pseudonymous handle, the match state, readiness and per-criterion status and evidence level (verified or reported). Never names, contact details, income or other renter values. Requires a verified organization.
| Argument | Type | Description |
|---|---|---|
vacancy_id | string (uuid) | The vacancy (offer) id, from list_vacancies. |
cursor | string | next_cursor from the previous page. |
limit | integer | Page size, 1–100 (default 25). |
create_qualification_link
Create a qualification link · scope write:links · creates data
Create a shareable “check if you qualify” link for a vacancy, tagged with the channel it will be shared on (e.g. zillow, facebook, email, buildium). Returns the URL. Only published vacancies show to renters.
| Argument | Type | Description |
|---|---|---|
vacancy_id (required) | string (uuid) | The vacancy (offer) id, from list_vacancies. |
channel | string | Where it will be shared, lowercase: zillow, facebook, craigslist, email, sms, buildium… Default: mcp. |
pause_vacancy
Pause a vacancy · scope write:offers · changes data
Take a published vacancy off the market. Pausing a paused vacancy does nothing. Resuming is publishing, which only a person can do in the PropFit app; confirm with the owner before pausing.
| Argument | Type | Description |
|---|---|---|
vacancy_id (required) | string (uuid) | The vacancy (offer) id, from list_vacancies. |
list_applications
List applications · scope read:applications · read-only
Applications for the organization’s vacancies (or one vacancy), in first-come order: status, criterion assertions, which kinds of data the renter shared, and the decision once a person made it in the app. Never names, contact details or renter values. Read only: deciding stays with a person in the app.
| Argument | Type | Description |
|---|---|---|
vacancy_id | string (uuid) | The vacancy (offer) id, from list_vacancies. |
status | submitted | in_review | screening_requested | screening_in_progress | screened | approved | declined | waitlisted | lease_recorded | withdrawn | expired[] | Only these statuses. Default: all. |
cursor | string | next_cursor from the previous page. |
limit | integer | Page size, 1–100 (default 25). |
get_application
Get an application · scope read:applications · read-only
One application: status, first-come position, criterion assertions, household roles, shared data kinds (not values) and the decision, if any.
| Argument | Type | Description |
|---|---|---|
application_id (required) | string (uuid) | The application id, from list_applications. |
background_check_status
Background check status · scope read:background_checks · read-only
Where an applicant’s background check stands (not requested, awaiting the renter, authorized, in progress, completed…). The result is only pass or needs_review; the report is read by the owner in the app.
| Argument | Type | Description |
|---|---|---|
application_id (required) | string (uuid) | The application id, from list_applications. |
request_background_check
Ask for a background check · scope write:background_checks · creates data
Ask an applicant to authorize the background check included in the plan, as “Request background check” in the app. The renter decides whether to authorize; ordering it stays in the app. Confirm with the owner first.
| Argument | Type | Description |
|---|---|---|
application_id (required) | string (uuid) | The application id, from list_applications. |
list_tour_times
List tour times · scope read:tours · read-only
Tour times (from yesterday on, unless from/to are given) and the tours booked in them, by pseudonymous prospect. Never contact details.
| Argument | Type | Description |
|---|---|---|
vacancy_id | string (uuid) | The vacancy (offer) id, from list_vacancies. |
from | string | ISO 8601: times ending after this (default: yesterday). |
to | string | ISO 8601: times starting before this. |
add_tour_times
Add tour times · scope write:tours · creates data
Add tour times to a published or paused vacancy. Start times are local wall-clock times in the vacancy’s market time zone, like 2026-11-09T10:00.
| Argument | Type | Description |
|---|---|---|
vacancy_id (required) | string (uuid) | The vacancy (offer) id, from list_vacancies. |
starts (required) | string[] | Local start times in the vacancy’s market time zone, like 2026-11-09T10:00. |
minutes | integer | Length (default 30). |
capacity | integer | Renters per time (default 1). |
cancel_tour_time
Cancel a tour time · scope write:tours · changes data
Cancel a tour time and every tour booked in it; the renters are told. Confirm with the owner first.
| Argument | Type | Description |
|---|---|---|
tour_time_id (required) | string (uuid) | The tour time id, from list_tour_times. |
cancel_tour
Cancel a tour · scope write:tours · changes data
Cancel one booked tour; the renter is told. Confirm with the owner first.
| Argument | Type | Description |
|---|---|---|
tour_id (required) | string (uuid) | The tour id, from list_tour_times. |
owner_report
Owner reports · scope read:reports · read-only
The owner reports: per vacancy, funnel and timing, plus details. Small groups are hidden.
| Argument | Type | Description |
|---|---|---|
since | string | ISO 8601: only activity since then. |
billing_summary
Billing summary · scope read:billing · read-only
Plan, billing status, active doors, subscription and recent invoice totals. Read only; never card details.
No arguments.
search_homes
Search homes · scope read:homes · read-only
Published homes in PropFit’s open markets, with rent, monthly and move-in cost, size, availability and pet policy, and the listing URL. Filter by market, area (city or ZIP), bedrooms and rent. Also lists the open markets.
| Argument | Type | Description |
|---|---|---|
market | string | An open market key (from open_markets). |
area | string | A city or ZIP code. |
min_bedrooms | integer | |
max_rent_cents | integer | Highest rent, in cents. |
cursor | string | next_cursor from the previous page. |
limit | integer | Page size, 1–100 (default 25). |
my_matches
My matches · scope read:my_matches · read-only
The renter’s own matches: each home, the match state, whether they qualify, and per criterion the explanation written for them, any gap and their next steps.
| Argument | Type | Description |
|---|---|---|
cursor | string | next_cursor from the previous page. |
limit | integer | Page size, 1–100 (default 25). |
my_applications
My applications · scope read:my_applications · read-only
The renter’s own applications and where each one stands.
No arguments.
my_tours
My tours · scope read:my_tours · read-only
The renter’s own booked and past tours, with the home’s address.
No arguments.
my_passport
My Passport · scope read:my_passport · read-only
Which of the renter’s checks (identity, income, credit) are verified, pending, expired or not started. Never the values.
No arguments.
notification_preferences
Notification preferences · scope read:notifications · read-only
The token creator’s notification and email preferences for this organization, quiet hours and daily cap.
No arguments.
When a tool fails
A missing scope, an unverified organization or a vacancy that can’t be paused comes back as a tool result with isError: true and a code: message text, so the assistant can explain it. The codes are the API’s error codes. A missing or invalid token is an HTTP 401.