SPACEXPLORATION
Search commercial real estate listings. Reads need no token; authoring is self-serve OAuth (DCR).
我该使用它吗
质量与安全性
基于对工具定义和协议合规性的自动分析。
上下文开销
这是每次将服务器的工具加载到模型上下文窗口时所消耗的大致 token 数。数值越高,可用于其他任务的注意力就越少。
安装
一键安装
将以下内容添加到你的 `claude_desktop_config.json` 文件中:
{
"mcpServers": {
"listings": {
"url": "https://spacexploration.com/mcp"
}
}
}远程端点
https://spacexploration.com/mcpstreamable-http它能做什么
工具清单
工具(15)
🟢get_registry
Returns the full attribute registry — every searchable and filterable field, its type, allowed values, and display label. Read this first to understand the schema before calling search_listings with attribute filters.
输入模式
{
"type": "object",
"properties": {}
}🟢search_listings(query, filters, sort, page, bounds)
Search commercial real estate listings. Returns paginated hits with facet counts. For AI-driven search, call interpret_search first to convert a natural-language query into structured filters, then pass those filters — and its bounds, when present — here.
输入模式
{
"type": "object",
"properties": {
"query": {
"description": "Free-text search query (street address, city, or keyword). Omit or pass null for no text filter.",
"type": [
"string",
"null"
]
},
"filters": {
"description": "Structured filter map keyed by Typesense field name. Ranges as {min?, max?}, multi-select as string[], booleans as true/false. Call get_registry to see valid field names and allowed values.",
"type": [
"object",
"null"
]
},
"sort": {
"description": "Sort key. Valid values from get_registry sort_options (e.g. \"listed_at:desc\", \"price:asc\").",
"type": [
"string",
"null"
]
},
"page": {
"description": "Page number (1-based). Defaults to 1.",
"type": [
"integer",
"null"
]
},
"bounds": {
"description": "Geographic bounding box (degrees) limiting hits to an area. Forward the bounds returned by interpret_search verbatim to honour \"near <place>\" intent; omit for a nationwide search.",
"properties": {
"sw_lat": {
"minimum": -90,
"maximum": 90,
"type": "number"
},
"sw_lng": {
"minimum": -180,
"maximum": 180,
"type": "number"
},
"ne_lat": {
"minimum": -90,
"maximum": 90,
"type": "number"
},
"ne_lng": {
"minimum": -180,
"maximum": 180,
"type": "number"
}
},
"type": [
"object",
"null"
]
}
}
}🟢get_listing(hashid)
Retrieve the full details of a single listing by its hashid. Returns the complete ListingResource projection including parcel data, all attribute details, and attachments. Broker contact is included only when the requesting user is authorised.
输入模式
{
"type": "object",
"properties": {
"hashid": {
"description": "The short hashid of the listing (e.g. \"a1b2c3d4\"). Found in listing URLs and search hits.",
"type": "string"
}
},
"required": [
"hashid"
]
}🟢interpret_search(prompt)
Translate a natural-language property-search sentence into a structured filter payload compatible with search_listings. Use this as a transparent intermediate step: pass the user's raw query here, then forward the returned filters — and the returned bounds, when present (they carry the "near <place>" intent) — to search_listings.
输入模式
{
"type": "object",
"properties": {
"prompt": {
"description": "A natural-language property search sentence from the end user. Example: \"industrial with rail access in Denver under $5m\".",
"type": "string"
}
},
"required": [
"prompt"
]
}🟡save_search(name, query, filters)
Save the current search as a named alert. The user will receive email digests when new matching listings appear. Requires authentication.
输入模式
{
"type": "object",
"properties": {
"name": {
"description": "A human-readable name for the saved search. If omitted, a name is derived from the filters.",
"type": [
"string",
"null"
]
},
"query": {
"description": "The free-text query string, if any.",
"type": [
"string",
"null"
]
},
"filters": {
"description": "The structured filter map to persist (same shape as search_listings filters).",
"type": [
"object",
"null"
]
}
}
}🟢list_my_saved_searches
List the authenticated user's saved searches, including their filters and alert schedule. Requires authentication.
输入模式
{
"type": "object",
"properties": {}
}🔴delete_saved_search(id)
Delete a saved search by its ID. Only the owner may delete their own searches. Requires authentication.
输入模式
{
"type": "object",
"properties": {
"id": {
"description": "The numeric ID of the saved search to delete (from list_my_saved_searches).",
"type": "integer"
}
},
"required": [
"id"
]
}🟢list_my_listings(status)
List all listings owned or brokered by the authenticated user. Optionally filter by status. Requires authentication.
输入模式
{
"type": "object",
"properties": {
"status": {
"description": "Filter by listing status. One of: draft, pending_payment, active, suspended, sold, leased, withdrawn. Omit to return all statuses.",
"type": [
"string",
"null"
]
}
}
}🟢geocode_address(address)
Geocode a free-form US address into coordinates and structured components (street_address, city, county, state, postal_code) plus a formatted address and place_id — exactly the identity fields create_listing requires. Use this first, then pass the result straight into create_listing instead of supplying your own coordinates.
输入模式
{
"type": "object",
"properties": {
"address": {
"description": "Free-form address to geocode, e.g. \"3763 Imperial St, Frederick, CO 80516\".",
"type": "string"
}
},
"required": [
"address"
]
}🟡create_listing(street_address, city, county, state, postal_code, ...)
Create a new draft listing. Returns the full created listing exactly as stored, including its hashid and status. Pass an idempotency_key (any client-generated string, e.g. a UUID) to make the call safe to retry — re-sending the same key returns the original listing instead of creating a duplicate.
输入模式
{
"type": "object",
"properties": {
"street_address": {
"description": "Street address of the property.",
"type": "string"
},
"city": {
"description": "City.",
"type": "string"
},
"county": {
"description": "County.",
"type": "string"
},
"state": {
"description": "State (2-letter abbreviation).",
"type": "string"
},
"postal_code": {
"description": "ZIP/postal code.",
"type": "string"
},
"latitude": {
"description": "Latitude coordinate.",
"type": "number"
},
"longitude": {
"description": "Longitude coordinate.",
"type": "number"
},
"property_type": {
"description": "Property type. Allowed values are listed under the property_type attribute returned by get_registry (e.g. industrial, office, retail, land).",
"type": "string"
},
"listing_type": {
"description": "Listing type: sale or lease.",
"enum": [
"sale",
"lease"
],
"type": "string"
},
"unit": {
"description": "Unit or suite number, if applicable.",
"type": [
"string",
"null"
]
},
"formatted_address": {
"description": "Full formatted address string from geocoder.",
"type": [
"string",
"null"
]
},
"place_id": {
"description": "Place ID from geocoder.",
"type": [
"string",
"null"
]
},
"idempotency_key": {
"description": "Optional client-generated key (e.g. a UUID) making this create safe to retry: re-sending the same key within 24 hours returns the originally created listing instead of a duplicate.",
"type": [
"string",
"null"
]
}
},
"required": [
"street_address",
"city",
"county",
"state",
"postal_code",
"latitude",
"longitude",
"property_type",
"listing_type"
]
}🟡update_listing(hashid, parcel, pricing, marketing)
Update a listing's parcel, pricing, or marketing data. Pass at least one group (parcel, pricing, marketing); send each group whole, not just the changed field. Returns the full updated listing exactly as stored.
输入模式
{
"type": "object",
"properties": {
"hashid": {
"description": "Hashid of the listing to update.",
"type": "string"
},
"parcel": {
"description": "Parcel/address fields to update: street_address, city, county, state, postal_code, latitude, longitude, and optionally unit, lot_size (INTEGER SQUARE FEET — convert acres × 43,560), lot_size_unit (the unit the size was stated in: sqft | acres | sqm | hectares; display-only), year_built, property_type.",
"type": [
"object",
"null"
]
},
"pricing": {
"description": "Pricing fields to update: listing_type (sale|lease); for a sale set sale_price (dollars), for a lease set lease_rate (per the lease_rate_period basis, default per_sqft_year) and optionally lease_rate_period (per_sqft_year|per_sqft_month|per_month|per_year). Omit the price and set price_on_request=true for \"price upon request\". Optionally expires_at (ISO date).",
"type": [
"object",
"null"
]
},
"marketing": {
"description": "Marketing copy to update: headline, summary, title_override, highlights (string[]).",
"type": [
"object",
"null"
]
}
},
"required": [
"hashid"
]
}🔴set_listing_attributes(hashid, attributes)
Set broker-authored attributes on a listing you own. Pass `attributes` as a map of registry field name to value (the field names get_registry returns, e.g. {"attr_parking_spaces": 40, "attr_office_class": "Class A"}). Only fields get_registry marks "writable":true can be set; publish-time computed fields and hot columns (use update_listing for those) are rejected with guidance. Enum fields take the allowed value (or an array for multiselect); send null to clear a field. Returns the full updated listing.
输入模式
{
"type": "object",
"properties": {
"hashid": {
"description": "Hashid of the listing to update.",
"type": "string"
},
"attributes": {
"description": "Map of registry field name to value, e.g. {\"attr_parking_spaces\": 40, \"attr_office_class\": \"Class A\", \"attr_industrial_rail_access\": true}. Only fields get_registry marks \"writable\":true are accepted. Multiselect enum fields take an array of allowed values. Send null to clear a field.",
"type": "object"
}
},
"required": [
"hashid",
"attributes"
]
}⚪attach_listing_photo(hashid, source_url)
Attach a photo to a listing you own directly from its public URL — one call, no separate sign/upload/confirm. The server fetches the image and ingests it with auto-generated thumbnail/hero/full variants. Only https image URLs whose host is publicly routable are accepted. The photo is content-moderated (must be real-estate related and safe) before it can appear publicly — the returned snapshot includes the moderation_status (approved / rejected / escalated) and moderation_reason. A rejected or escalated photo will not be publicly visible and will block publishing until removed or replaced.
输入模式
{
"type": "object",
"properties": {
"hashid": {
"description": "Hashid of the listing to attach the photo to.",
"type": "string"
},
"source_url": {
"description": "Public https URL of the image to fetch and attach. Must point directly at an image (jpeg, png, webp, gif, avif, heic/heif) on a publicly-routable host.",
"type": "string"
}
},
"required": [
"hashid",
"source_url"
]
}🟡sign_attachment_upload(attachable_type, attachable_id, filename, content_type, size, ...)
Begin an out-of-band file upload. Returns a presigned R2 PUT URL and the headers to use; the file bytes are uploaded directly to storage, never through this channel. After PUTting the file, call confirm_attachment_upload with the returned attachment_id. Supports listings (photos, documents), users (avatar), and pages (cover, photos).
输入模式
{
"type": "object",
"properties": {
"attachable_type": {
"description": "Morph alias of the resource to attach to: \"listing\", \"user\", or \"page\".",
"type": "string"
},
"attachable_id": {
"description": "Identifier of the attachable resource. For \"listing\" pass the listing hashid (e.g. \"d5yqqgoa\") — the same id every read tool returns. For \"user\" pass \"me\" to attach to yourself. For \"page\" pass its numeric id.",
"type": "string"
},
"filename": {
"description": "Original filename including extension, e.g. \"front-elevation.jpg\". Used to derive the storage key and extension.",
"type": "string"
},
"content_type": {
"description": "MIME type of the file, e.g. \"image/jpeg\" or \"application/pdf\". Must match the collection whitelist.",
"type": "string"
},
"size": {
"description": "Exact byte size of the file. Verified against the uploaded object at confirm time, so it must be accurate.",
"type": "integer"
},
"collection": {
"description": "Optional explicit collection: \"photos\", \"documents\", \"avatar\", \"logo\", or \"cover\". Omit to auto-route by MIME (images→photos, docs→documents). Singleton slots (avatar/cover/logo) must be set explicitly.",
"type": [
"string",
"null"
]
}
},
"required": [
"attachable_type",
"attachable_id",
"filename",
"content_type",
"size"
]
}🟡confirm_attachment_upload(attachment_id)
Finalize an out-of-band upload after the file bytes have been PUT to the presigned URL. Verifies the stored object matches what was signed (size and content-type) and marks the attachment ready. Returns the attachment snapshot with its public variant URLs. Idempotent: confirming an already-confirmed upload returns the same snapshot.
输入模式
{
"type": "object",
"properties": {
"attachment_id": {
"description": "The attachment_id (ULID) returned by sign_attachment_upload. Confirm only after the file bytes have been successfully PUT to the presigned URL.",
"type": "string"
}
},
"required": [
"attachment_id"
]
}社区
证据