AI agents and MCP

AI agents and MCP

In short

In Claude, connect Fabrica from the Claude directory. In any other assistant that supports remote MCP servers (ChatGPT, Cursor and others), add https://mcp.fabrica.land/mcp. The assistant can then look up Fabrica properties, any US parcel, the lending market, portfolios and cited answers from these docs. No API key, account or wallet is needed for public data; a person who signs in to Fabrica also lets it read their own properties, offers and loans. Reading never changes anything. The server can also prepare an offer, a listing, a purchase, a loan, a payoff, a lending pool deposit or an owner's change to their property as a sign request: the person reviews it and signs on fabrica.land with their own account, and the server never signs or sends anything. A separate testnet server serves test properties for trying this first.

The Fabrica MCP server gives AI agents access to the data behind the Fabrica protocol and to Fabrica's own documentation: Fabrica properties, any US parcel by address or parcel number, the lending market and its history, account portfolios, protocol-wide statistics, parcel geometry, map images, the trust documents attached to a token, and cited answers from the docs, the help center and the trust agreement. It implements the Model Context Protocol (MCP), the open standard that assistants and agent frameworks such as Claude, ChatGPT, and Cursor use to call external tools, so any MCP client that supports remote servers can connect to it.

It serves two audiences: people who use an AI assistant and want it to answer questions about Fabrica properties from live data, and developers building agents that reason over real property on Fabrica.

The public tools read data already available through the Fabrica GraphQL API or published on Fabrica's sites, and need no API key, account, or wallet. The account tools read the connected person's own account, after that person signs in to Fabrica and approves read-only access. On both networks the server also prepares marketplace, borrowing, lending pool and owner actions as sign requests: the agent prepares, and the person reviews and signs on fabrica.land with their own account.

Hosted Endpoints

NetworkURLData
Ethereum mainnethttps://mcp.fabrica.land/mcpReal US parcels. Responses carry a legal notice. Read tools and the sign request tools, including owner changes.
Sepolia testnethttps://mcp-testnet.fabrica.land/mcpTest properties only. The same read tools and sign request tools.

The network is fixed per URL: an agent connected to the testnet server cannot reach mainnet data, and vice versa. Add both as separate servers if you want to try things on testnet before mainnet.

The hosted server is stateless. Each request is served by a fresh server instance with no session, the transport is Streamable HTTP with JSON responses, and only POST is accepted on the MCP path (a GET returns 405, and a request body over 1 MB is refused with 413). Browser-based clients can call it directly, since responses carry permissive CORS headers. The hosted endpoints are deployed from the main branch of the public repository, so they track its current tool set, and both serve the property card described below.

Discovery

Each host describes itself without a registry. https://mcp.fabrica.land/.well-known/mcp.json gives the server URL, transport, authentication (none), the documentation link, the skill file and the other network's server; /.well-known/mcp/server-card.json adds every tool with its title and annotations, the prompts and the resource templates, read from the running server so it always matches what that host registers; and /.well-known/ai-catalog.json is the AI Catalog that domain-level discovery reads first, pointing at both servers' cards. The testnet host serves the same documents for itself. The repository also carries the entries for the official MCP Registry (land.fabrica/mcp and land.fabrica/mcp-testnet, remote servers with no package).

Connecting

Claude (claude.ai, the desktop app and mobile): Fabrica is listed in the Claude directory. Open Fabrica in the Claude directory and select Connect. To add it by hand, or to add the testnet server: Settings, then Connectors, then Add custom connector, and paste the URL.

Claude Code:

claude mcp add --transport http fabrica https://mcp.fabrica.land/mcp
claude mcp add --transport http fabrica-testnet https://mcp-testnet.fabrica.land/mcp

Cursor: the repository README carries a one-click "Add to Cursor" link for the mainnet server, or add it by hand in .cursor/mcp.json:

{
  "mcpServers": {
    "fabrica": { "url": "https://mcp.fabrica.land/mcp" }
  }
}

Any other client that supports remote MCP servers over Streamable HTTP is configured the same way.

Running Locally

The server also runs locally over stdio from a clone of the repository. It is not published to npm, so install from source (Node 20 or later, with Yarn; run corepack enable if yarn is not installed):

git clone https://github.com/fabrica-land/fabrica-mcp.git
cd fabrica-mcp
yarn install
yarn build

Then point your client at the built entry point. With Claude Code:

claude mcp add fabrica -- node /absolute/path/to/fabrica-mcp/dist/index.js

With Claude Desktop (claude_desktop_config.json), here selecting Sepolia:

{
  "mcpServers": {
    "fabrica": {
      "command": "node",
      "args": ["/absolute/path/to/fabrica-mcp/dist/index.js"],
      "env": { "FABRICA_NETWORK": "sepolia" }
    }
  }
}

A local server connects to Ethereum mainnet unless told otherwise. All environment variables are optional:

VariableDefaultPurpose
FABRICA_NETWORKethereumethereum or sepolia
FABRICA_API_URLhttps://api.fabrica.land/graphqlFabrica GraphQL API the tools read from
FABRICA_METASTREET_SUBGRAPH_URLselected per networkSubgraph the server reads lending-pool statistics from (the variable keeps its original name)
FABRICA_MEDIA_URLhttps://media.fabrica.landMedia service that renders the map images
FABRICA_MCP_APPSenabled on Sepolia, disabled on mainnetenabled or disabled: whether get_land_property also serves the property card
FABRICA_SIGN_REQUESTSenabled on Sepolia, disabled on mainnetenabled or disabled: whether the sign request tools are registered. A local server keeps pending requests in memory
FABRICA_POOL_SIGN_REQUESTSenabled on Sepolia, disabled on mainnetenabled or disabled: whether deposit_to_lending_pool and withdraw_from_lending_pool are registered (only when sign requests are on)
FABRICA_LIST_WHILE_ADDINGenableddisabled stops list_land_for_sale from preparing a listing for a property its owner is still adding
FABRICA_OWNER_ACTIONSenabled on Sepolia, disabled on mainnetenabled or disabled: whether the owner change tools are registered (only when sign requests are on)

Your own account (sign-in)

The same URL serves public reads and the connected person's own account. Public tools answer without sign-in. The first time an account tool is called, or me is passed as a wallet argument, the server answers HTTP 401 with an MCP authorization challenge (OAuth 2.1 with PKCE using S256, and dynamic client registration). When dynamic client registration is enabled, the Fabrica API registers the client at POST /oauth/register. The client opens fabrica.land, where the consent page names the client, and the person signs in. The consent page shows one label for each scope. The profile:read label is "See your email, linked accounts and verification status". Approving sends the person back to the client: the page says it is taking them back to that client and names the host it returns to. The client then retries the same call. The connection reads only what was approved. A missing portfolio:read grant tells the person to approve "See your properties, listings, offers and loans". A missing onramp:read grant tells the person to approve "See the properties you're adding to Fabrica". The person can disconnect it at any time from Connected apps in their account menu on fabrica.land. A valid token on any request makes that session the person's own. A revoked grant stops on the next personal read: the Fabrica API answers 401, and the token expires within its 15-minute lifetime. The API issues a refresh token and rotates it when the client uses it. The client asks for a new access token with the refresh_token grant. The token is never logged and never cached. A signed-in response sets Cache-Control: no-store.

Fabrica's sign-in for AI agents never asks for or receives a password. You sign in through Dynamic, and Fabrica receives only a session token.

On iPhone and iPad, connect from claude.ai in Safari: the Claude iOS app's in-app browser cannot complete the Fabrica sign-in. Once connected, the connection works in the app too.

ToolReturns
get_my_accountEmail, linked accounts (every wallet address on the account), verification status, and the scopes the connection holds with its token expiry
get_my_propertiesThe person's properties across every wallet on the account: those being added first, then live properties by estimated value, with stage, status, location, acres, listing price, offers waiting, whether it is under a loan, Property checks encoding, estimated value and the property page link
get_my_offersOffers received on the person's properties (highest first, with whether the property is under a loan) and offers the person made
get_my_loansLoans against the person's properties (maturity, payoff today, APR), loans they funded, and their position in the DeFi lending pool
what_needs_attentionOne ranked list of what waits on the person: loans past or near maturity, offers, steps of properties being added, fees to approve, and checks on live properties
get_my_properties_being_addedProperties the person is adding to Fabrica, with status, steps done, and the next step with who acts
get_adding_statusOne property being added in full: every step with its status and dates, the next step, and the actions open on it

Public tools keep working after sign-in. get_land_portfolio and get_land_portfolio_map_image read the connected person's own wallet when address is left out. get_land_activity and search_land (ownedBy) take me for that wallet. Before sign-in, me on a wallet argument is a call that starts sign-in. Signed in, and when the connection holds portfolio:read, estimate_land_borrowing is read as the connected person, so the borrowing capacity is theirs. The amount stays an estimate. A live quote sets the rate only when the person borrows.

The account tools only read. Listing, accepting an offer, repaying and depositing are prepared by the sign request tools and signed by the person on fabrica.land.

What the Server Can and Cannot Do

Every read tool says so in the standard MCP way: it is registered with a human-readable title and with annotations readOnlyHint: true, destructiveHint: false, and idempotentHint: true, so a client that gates state-changing tools behind confirmation can treat a Fabrica lookup as a plain read. The server queries the public Fabrica GraphQL API (plus a lending-pool subgraph for pool statistics, the Fabrica media service for map images, a public parcel search for addresses and parcel numbers, and the chain itself for transaction status) and returns formatted results. It holds no keys, signs nothing, and submits nothing onchain or to the API.

The sign request tools, registered on both hosts, are annotated readOnlyHint: false because each writes a short-lived record to the server's own store. They still move no token or funds: they check the live data and return a link to fabrica.land where the person reviews the prefilled dialog and signs with their own account. See Sign requests.

Mainnet legal notice. On the mainnet endpoint, the server's instructions carry a legal notice written as a statement of facts rather than as directions to the agent. It states that Fabrica properties are real parcels of land in the United States, each held in a trust whose beneficial interest is represented by an ERC-1155 token, and that acquiring, transferring, listing, or borrowing against a token has real-world legal and financial consequences: owning a token means owning the beneficial interest in the trust that holds the property, with the trustee designated by the token holder and by default the holder; owners can carry obligations tied to the land, such as property taxes, maintenance, and environmental liability; transfers and sales are legally binding and can trigger tax events such as capital gains or transfer taxes; the operating agreement (the trust instrument) attached to each token sets out the owner's rights and obligations, and its URL is included in property details; and the data is informational, not financial or legal advice. Property search, property detail, order book, and protocol statistics responses on mainnet also carry a one-sentence version of the notice. The testnet server states instead that its properties are test tokens with no real-world legal or financial effect, and its prompts ask the agent to label every result as test data.

The instructions also tell an agent to answer questions about how Fabrica works from ask_fabrica, citing the URL of the passage it relied on, and to say so and point to support rather than guess when no passage matches.

Default filters. Property searches and protocol statistics exclude retired tokens, properties still being added, and tokens below a minimum numeric encoding of Property checks, together with a small set of known spam entries. The default minimum is 72,032, the same threshold the Fabrica marketplace applies to its public listings; the API pairs any minimum with a verified-deed requirement, so the default leaves out every property the marketplace would not sell, including any whose recovery status is not Normal. The minScore input of search_land (the minimum numeric encoding) overrides the default. A search with ownedBy and no minScore lists every property in that account, as the owner's own holdings appear in the application, and get_land_portfolio applies no minimum.

Owner names. The deed grantor from Fabrica's own records and a holder's chosen display name are returned where the application shows them. Owner names from third-party parcel data are never returned, and find_us_parcel strips them before answering.

Errors and limits. Tools return an error field with a plain-language message instead of raising, and a result that carries one is flagged with the MCP isError marker so clients can tell failure from data. A property that does not exist is reported as such; a failure of the underlying API is reported as an API error carrying the API's own message, so an agent can tell the two apart. A request to the underlying API that does not answer within 20 seconds is reported as an error that suggests retrying, and a map image larger than 5 MB is refused with a request for smaller dimensions. The county outline in get_land_boundary is an extra layer: if it cannot be fetched, the parcel geometry is still returned and the failure is listed under warnings. find_us_parcel uses a metered third-party lookup, so it is limited to 30 lookups per minute per client (each query in a list counts as one), and the limit is reported as a plain error. Reads are cached briefly and responses are bounded in size; long lists are paged with limit and offset.

Tool Reference

Twenty-one public read tools on both hosts, and fifteen sign request tools on both hosts, four of them for owner changes. Seven account tools are registered when Connect Fabrica is enabled for that server. Inputs marked with an asterisk are required; every other input is optional. Property tools accept either a tokenId or the property slug from its Fabrica URL (for example us/nevada/elko-county/elko/apn-063025003), and the id of a property record replaced when its token was issued resolves to its successor.

ToolInputsReturns
search_landregion (US state code), county, groupBy (state or county), minAcres, maxAcres, minScore, hasListings, hasLoans, ownedBy (account address, or me once signed in), minPrice, maxPrice, minPricePerAcre, maxPricePerAcre (listed properties only), near (a point, with the radius), sortBy (price, pricePerAcre, acres, estimated value, Property checks, newest, distance), sortDir, limit (default 20, max 100), offsetMatching properties with location, acreage, the numeric encoding of Property checks, estimated value, listing price, price per acre (listing or estimate, labeled), lifecycle stage, loan flag, owner, property link and, with near, the straight-line distance; or, with groupBy, one row per state or county with the property count, the count for sale, total acres and the link to that location's page on fabrica.land. The total match count is returned for paging
get_land_propertytokenId or slug, display (inline or fullscreen, for hosts that render the card)Full detail: location, legal description and trust name, operating agreement URL, Property checks (how many pass, with each check's result and the numeric encoding), property tax status, valuation with per-source pricing, ownership and holders, active loans and DeFi lending pool capacity, active listings and offers, the owner's description and photos (up to eight, with resized thumbnails) and parcel map image links in both themes, recent activity, the lifecycle stage (unclaimed, being added, live, removal in progress, removed, retired), fees assessed on the token with their approval and payment state, flags for a duplicate parcel claim or a marketplace screen, and warnings for recovery, default, or liquidation status. Boundary geometry comes from get_land_boundary
get_land_boundarytokenId or slug, includeCountyBounds (default false)GeoJSON FeatureCollection with the parcel boundary (or a point when no boundary exists) and, on request, the county outline
get_land_map_imagetokenId or slug, theme (dark by default, or light), width, height (100 to 1280 pixels, default 640)Inline static map image of the parcel boundary, or a pin when no boundary exists
get_land_trust_documentstokenId or slug, includeAgreementText (default false)The legal record: the trust that holds the property (holding entity, formation date), the trust agreement that governs the token (name, version, link, and the full text on request), the legal description, the parcel identifiers (FIPS, APN, county, state), the recorded deed reference and grantor, and the documents the owner uploaded. trust.agreementResource names the MCP resource that serves this token's own agreement
get_land_tax_statustokenId or slugWhether the property's taxes are current, past due or unknown according to Property checks, which signal says so (the Property Taxes Current check, the DeFi lending pool's block reason, both, or a note that they disagree), when it was checked and when the checks expire, and whether it limits borrowing. A data lookup, not the county's own statement; the amount due and the due date are not available
explain_property_checkstokenId or scoreExplains Property checks: a digit-by-digit breakdown of the numeric encoding's five groups against the 75,342 maximum, with the individual check results when a token is given. The result states that the encoding is positional, not a percentage or a grade, and no percentage is reported
get_land_valuationtokenId or slugEvery value the API holds for the property, each with its source, date and confidence: the estimate and the sources it comes from, the Fabrica AVM, third-party and county assessor figures, the signed valuations the DeFi lending pool reads, the pool's oracle state (feed freshness, onchain price, usable price) with the reason when a price is missing, and the valuation report link. It presents data with its provenance and suggests no price
estimate_land_borrowingtokenId or slug, amountUsd (a loan amount to test)DeFi lending pool availability for the property (the advertised maximum principal in whole USDC, rounded down, subject to available pool liquidity, and the available durations), any active loan on it, the reasons when the pool shows no capacity, limits naming what binds the amount (pool liquidity, loan-to-value, pool limit, tax status, oracle, or an existing loan) with the collateral price, the pool's free liquidity and the highest loan-to-value, how the collateral price is derived from the valuation sources, and toRaise, one entry per lever (adding the property, tax status, the deed check, fees, an existing loan, price, loan-to-value, pool liquidity) with where it stands and the step that moves it. The amount is an estimate; the amount and rate are set by a live quote when borrowing. Signed in, with portfolio:read, this read is as the connected person
get_loan_against_landtokenId or slug, loanIdOne loan against a property: status (active, repaid, liquidated), provider, principal, APR, start, maturity, the full repayment and, while active, the payoff today, with the borrower and lender accounts shortened and the property link. A property alone gives its active or latest loan; loanId alone is looked up across the network; otherLoans lists the property's other loans
get_land_order_booktokenId or slug, status (active by default, or all), minOfferUsdThe lowest active listing, all listings, and offers from highest to lowest, each with price in US dollars and in its currency, seller or buyer, expiry (ISO 8601 and relative), the marketplace fee on a listing, any buyer restriction and disclosure documents, and for a property under a loan each listing's encumbrance (whether it can be bought now and, if not, why). Expired, canceled and filled orders are included only with status: all
get_land_activitytokenId, slug, or address (or me once signed in); type (for example loan, transfer, sale, mint); limitEvent timeline for a property or an account: mints, transfers, sales, listings, loans started, repaid, or liquidated, and configuration changes. With no property or address, the most recent activity across the whole network
get_fabrica_lending_marketstatus (active, repaid, liquidated, all), borrower, lender, since (ISO date), limit (default 20, max 100)Market summary (loans by status, loan volume per currency, average APR of active loans), DeFi lending pool statistics (value locked, in use, available, utilization, loan counts), matching loans with their terms and venue, and the ten most recent loan events
get_fabrica_loan_bookprovider (pool or peer-to-peer), status, sinceDays, groupBy (state, provider, status, loan-to-value band, acre band), largest (default 10, max 25)The lending history as a distribution: loan counts and principal by status and provider, loan-to-value bands against today's property estimates, exposure by state and acreage, APR and duration spread, repaid and liquidated counts, originations by month for the last 12 months, and the largest loans with their property pages. Where the pool data source's counters differ from the loan records, both are shown
get_land_portfolioaddress (required on a public call; once signed in, leave it out to read the connected person's own wallet), limit (default 50, max 200), offsetProperties held (paged), lending positions as borrower and as lender, credit history, marketplace activity, and total portfolio value for an account, scoped to the server's network and token contract; counts and totals always cover the whole account. The outstanding-loans total is null when a loan has no dollar price
get_land_portfolio_map_imageaddress (required on a public call; once signed in, leave it out to read the connected person's own wallet), theme, width, heightInline static map with every property held by the account plotted as points
get_fabrica_statsnoneProtocol-wide figures: token count and estimated value, states represented, loan counts and loan volume per currency, lending-pool statistics, active listings, and the token contract address (on mainnet, the retired peer-to-peer lending contracts are listed separately as historical)
ask_fabricaquestion*, maxPassages (1 to 10, default 5), source (docs, help, trust-agreement, or all)The best matching passages from docs.fabrica.land, the help center and the US trust agreement, each with its URL, so an answer can be cited. Retrieval is lexical over an index committed in the repository, with no model call and no external service; when the question names a specific property, account or listing, the result also suggests which lookup tool to call
find_us_parcelquery (a street address or parcel number) or queries (up to 10 sharing one state and county), state, countyFor any US parcel: address, place, APN, state and county, and whether it is already on Fabrica (token id and property link). For a parcel not on Fabrica, links.addToFabrica is the fabrica.land on-ramp link for that parcel, which starts the process only when a person opens it and decides there; the tool itself creates nothing. An ambiguous query returns up to five candidates, and state and county narrow it to one. A list returns one row per query
check_county_coveragefips (5-digit county code), or state with or without county; ownerType (individual, entity, concurrent)Whether the county (or state) can be added through the on-ramp (supported, not configured, or unsupported) and, for a supported county, the deed and forms the owner signs (and which are notarized), witness requirements, the questions the owner is asked, and the on-ramp steps. Answered from a table of the on-ramp rules with an as-of date, refreshed by hand; the on-ramp page is the live answer. No fee amounts and no owner data
contact_fabrica_supportsummary*, topic, tokenId, subject, discloseAgent (default true)The help center section for the topic, the support email address, and a mailto link that drafts an email with the summary and the property link. Nothing is sent by the tool; the person sends the email. A summary containing a private key or seed phrase is refused

Monetary values are formatted in US dollars where the source provides a dollar figure. Activity amounts are derived from the event's own currency amount and decimals: stablecoin amounts read as dollars and other currencies in their own unit (for example WETH), and the API's dollar figure is used only as a fallback. Loan principals are stated in the loan's own currency, and loan volumes are totaled per currency rather than summed across currencies or presented as dollars. Each loan and lending event names its venue: pool loans read as the DeFi lending pool, and loans made through the former peer-to-peer integration are labeled as retired. Borrow quotes list only the DeFi lending pool, since that integration has shut down (see Peer-to-Peer Lending). Loan counts are reported by status; the server does not publish an aggregate repayment rate. This table is derived from the server source and checked against the hosted endpoints; the tools/list response of the deployment you are connected to is authoritative.

Sign requests

On both hosts, nine tools prepare an action instead of reading: the marketplace's make_land_offer, list_land_for_sale, accept_land_offer, buy_land and cancel_land_order, borrowing from the DeFi lending pool with borrow_against_land and repay_loan_against_land, and lending to it with deposit_to_lending_pool and withdraw_from_lending_pool. The property tools take the property (tokenId or slug), the action's values, and wallet, the address that will sign. The tool checks the live data first (the property's token is issued, except for a listing, and it is not being removed, the wallet holds it or does not where that matters, the order is open, buyable and the wallet's own where it has to be, the property backs no active loan for a new borrow, the loan is open and the wallet is its borrower for a payoff, and the amount is within the pool's current maximum) and warns about a price far from Fabrica's estimate, an order about to expire, a listing at or below an offer, a loan on the property, or a loan past maturity. It then returns a signRequest: a summary of what the person will sign, the warnings, a signLink to the property page (or, for a deposit or withdrawal, the pool page) on fabrica.land with the matching dialog prefilled, and an expiresAt 15 minutes out. The request is stored in the server's own store; it never holds a key or a signature.

The person opens the link, signs in with that account, reviews the dialog, which is marked as prepared by an agent, and signs. The sign page accepts only the account the request was prepared for, repeats every check the button it stands in for would make, and submits nothing until the person confirms; a link for another property, a gone order or an expired request falls back to the plain page with a notice. An offer, a listing and accepting an offer are signatures; a purchase, a borrow, a payoff, a deposit and a withdrawal are onchain transactions sent by the person's own account; canceling an order is a signed-in confirmation with no transaction. The payload field of a sign request (the typed data or unsigned transaction a wallet inside the conversation could sign) is null: the order is built on the sign page from the person's own session.

ToolInputsPrepares
make_land_offerproperty, amountUsd, expiresDays (default 14), walletAn offer to buy a minted property, paid in USDC (one USDC counts as one dollar)
list_land_for_saleproperty, priceUsd, expiresDays (default 180), walletA listing of a property the account holds. A property its owner is still adding can be listed too: buyers can send offers at once, and the listing can be bought once the property's token is issued
accept_land_offerproperty, orderHash(the orderId from get_land_order_book), walletAccepting an open offer; signing sells the property, and the USDC less the marketplace fee shown on the sign page comes to the account at settlement
buy_landproperty, orderHash, walletBuying a property at its open listing; a listing on a property under a loan can be bought only once its payoff is ready, and the seller's disclosure documents are listed
cancel_land_orderproperty, orderHash, walletCanceling the account's own open listing or offer
borrow_against_landproperty, amountUsd, durationDays (the pool's offered length closest to it; default the one closest to 30 days), walletA loan from the DeFi lending pool against a property the account holds; the rate and repayment come from the pool's live quote on the sign page
repay_loan_against_landproperty, loanId (default the property's open loan), wallet*Paying off the open pool loan at the payoff amount today; a loan past maturity can be paid off until the pool's auction starts
deposit_to_lending_poolamountUsd, tick (left out with several open, the answer lists them), pool, walletA USDC deposit into one tick of the DeFi lending pool. A tick sets the largest loan it funds and the longest loan length; the pool issues deposit shares for the deposit. Interest is set by the pool, variable and not guaranteed, and deposits are at risk: a loan that is not repaid, and whose auction falls short, reduces the tick's value
withdraw_from_lending_pooltick, amountUsd (default the whole position), pool, walletA withdrawal from the account's deposit at a tick. It is paid from funds the tick has not lent out; the tool warns when part of it will wait in the pool's withdrawal queue, to be claimed later from the pool page
get_sign_requestid*Whether a request is pending or completed, with the order hash, transaction hash or loan id once signed. A pending request is also checked against the live order book, the property's loans for a borrow or payoff, or the pool's log for a deposit or withdrawal; an expired id is reported as unknown
get_transaction_statushash*The status of a transaction on the server's network (not found, pending, succeeded or failed) with the block, confirmations, sender, recipient and a block explorer link. Reads the chain only

These tools are registered on both hosts. On mainnet every signature or transaction is real and final once confirmed; on testnet it moves test tokens and test USDC only. The same sign links work for anyone, without the MCP server; see Prepared action links.

Owner changes

Four more sign request tools prepare an owner's change to a property they hold. Each takes the property, wallet* and the values below, checks that the wallet holds the share the contract requires and that the property backs no loan, and returns a sign link to the property page with the matching dialog open.

ToolInputsPrepares
transfer_landproperty, recipient, walletMoving the whole property to another account linked to the owner's own Fabrica login (a sale to someone else is a listing or an accepted offer). The sign page offers only those accounts. Final once the transaction confirms
update_trust_agreementproperty, wallet*Moving the property to the latest version of the Fabrica trust agreement; needs at least 70% of the property held directly. The sign page shows the latest version and says when the property already uses it. Final once confirmed: earlier versions are not offered
update_land_descriptionproperty, description, walletReplacing the property's description; needs at least 50%. The editor opens with the text filled in and editable before saving
update_land_photosproperty, wallet*Opening the property's photo editor; needs at least 50%. The owner picks, removes or reorders photos on the page; files do not pass through the server

Prepared action links

A property page URL, or a lending pool page URL for deposits and withdrawals, can carry an action and its values. The page opens the matching dialog filled in and marked as prepared by an agent, so an agent hands the decision to the person who signs. These links work with or without the MCP server.

ActionQuery stringWho uses it
Make an offer?action=offer&amount=<amount>&expires=<days>Buyer (Buying)
List for sale?action=list&price=<price>&expires=<days>Owner (Selling)
Buy a listing?action=buy&order=<listing id>Buyer (Buying)
Accept an offer?action=accept&order=<offer id>Owner accepting an offer (older links that buy a listing with accept still work)
Cancel your own listing or offer?action=cancel&order=<order id>Whoever placed the order
Borrow from the pool?action=borrow&amount=<amount>&duration=<days>Owner (Pool-Based Lending)
Repay a pool loan?action=repay&loan=<loan id>Borrower
Deposit into the poolpool page, ?action=deposit&tick=<tick>&amount=<amount>Lender (Pool-Based Lending)
Move to another of your accounts?action=transfer&to=<account>Owner
Update the trust agreement?action=trustOwner holding at least 70%
Edit the description?action=describeOwner holding at least 50%
Edit the photos?action=mediaOwner holding at least 50%
Withdraw from the poolpool page, ?action=withdraw&tick=<tick>&amount=<amount> (add &max=1 for the whole position)Lender with a deposit at that tick

Behavior:

  • A signed-out visitor signs in first.
  • A link for another account, another property, or an order that is no longer open falls back to the plain page with a notice.
  • Every number is shown as it will be signed, with the same checks as the button the link stands in for (and, for borrowing, the pool's live quote).
  • Nothing is sent or signed until the person confirms.

Prompts and the skill file

Both hosts offer four MCP prompts, the standard loops written once so every client runs them in the same order and to the same standard: due_diligence (one property, from its record through Property checks, tax status, valuation with sources, the order book, the trust documents, the lending position and the activity, ending with what to verify independently and never a buy recommendation), work_parcel_list (a list of addresses or parcel numbers through find_us_parcel, ending in one table), wallet_review (holdings, loans as borrower and as lender with their maturities, and what needs attention soon) and how_to_add_land (the on-ramp for one parcel, with the fees and the obligations that stay with the owner). Each prompt carries the wording rules (Property checks are a starting point, not a title search; no fixed time for money moving; no buy, sell or borrow recommendation) and the network's legal notice.

The same loops, the tool list and the legal red lines are published as an Agent Skills file at https://mcp.fabrica.land/skill.md (source: skills/fabrica/SKILL.md in the repository), for agents that never connect to the server.

Resources

Fabrica's documents are registered as MCP resources, so a person can attach one to a conversation from the client's resource picker without the agent searching for it. All are text/markdown, and every read starts with the source URL and the content's updated date.

URIWhat it is
fabrica://docs/<slug>Every page of this documentation, by slug (the most used pages are listed first)
fabrica://help/<id>Every help center article, by its article id and slug
fabrica://legal/us-trust-agreementThe current US trust agreement text
fabrica://property/{tokenId}/trust-agreementThe operating agreement attached to one token, as the API serves it (versions differ by mint date)
fabrica://networkThe server's network, contract addresses and legal notice

fabrica://docs/{slug} and fabrica://help/{id} are also resource templates with completion. The index behind ask_fabrica and these resources is built from the docs, the help center and the trust agreement, committed in the repository, and refreshed by a scheduled workflow that opens a pull request when a source changes, so the hosted servers never fetch the sources at runtime.

Property Card (MCP App)

In clients that support MCP Apps, such as Claude on the web and in the desktop app, get_land_property renders a property card inline in the conversation instead of a block of JSON. The card shows:

  • a gallery with the parcel map first, followed by the owner's photos when the property has any
  • the property name, location, and acreage
  • how many Property checks pass (for example "16 of 18 pass", as on fabrica.land), estimated value, listing price, and borrowing capacity
  • Buy (when the property is listed and its token has been issued), Make an offer, Contact owner, and View on Fabrica buttons

Every button opens the property's page on Fabrica, where the user completes the action and signs with their own account. The card changes how the data is shown, not what the server can do. Clients without MCP Apps support receive the same data as JSON. The card adapts to where the host shows it (a phone, inline in the conversation, or fullscreen), and the agent can ask for it fullscreen with display: "fullscreen"; the host may decline.

The card is served as an MCP resource at ui://fabrica/property-card, and the get_land_property tool points to it through its metadata; a client that supports MCP Apps picks it up automatically. It renders in the client's sandbox and loads images only from Fabrica's IPFS gateway, the Fabrica media service, and the map-tile provider behind it. Both hosted endpoints serve the card. A local server serves it by default on Sepolia and not on mainnet; set FABRICA_MCP_APPS=enabled to turn it on there, or disabled to turn it off.

Repository

The server is developed in the public repository github.com/fabrica-land/fabrica-mcp under the MIT license. The repository also holds a checked-in snapshot of the GraphQL schema that every query is validated against, so an upstream API change surfaces as a reviewable diff rather than a runtime failure, the committed knowledge index, a regression list that calls every tool on a hosted server, and the manifests that package the same hosted server as a ChatGPT and a Cursor plugin.

Documentation server

https://docs.fabrica.land/mcp gives agents this documentation and the API reference. Add it the same way when an agent needs to answer questions about the protocol, the trust, or the API; the Fabrica server's ask_fabrica covers the same documentation together with the help center and the trust agreement.

Other resources for agents

  • fabrica.land/llms.txt: a summary of Fabrica written for language models, served as text/markdown, listing the hosted MCP servers, the skill file, the GraphQL endpoint, the token contract and the documentation. Every page of fabrica.land points to it with Link: </llms.txt>; rel="describedby" and rel="llms-txt" headers, and a request for the homepage with Accept: text/markdown returns it in place of the HTML (other pages are not served as markdown)
  • mcp.fabrica.land/skill.md: the Agent Skills file described above
  • GraphQL API at https://api.fabrica.land/graphql: public, no API key, introspection enabled

Related


Did this page help you?