> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Connect AI agents to the Mireye MCP server

The Mireye MCP connector routes your AI agent's tool calls to Mireye's own MCP server through Scalekit. Each user signs in to Mireye once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 9 tools.

**Authentication:** OAuth 2.1/DCR
**Categories:** Search, Analytics, AI
**Tools:** 9: 8 read, 1 write, 0 destructive
**Users sign in with:** OAuth
**OAuth app:** Your own Mireye MCP server app
**Built by:** Vendor MCP
**Try it:** [Playground in the Scalekit dashboard](https://app.scalekit.com/ws/signup?sk_intent=playground&provider=MIREYEMCP)

## Setup

1. ### Install the SDK

   **Node.js**

   ```bash
   npm install @scalekit-sdk/node dotenv
   ```

   **Python**

   ```bash
   pip install scalekit-sdk-python python-dotenv
   ```

2. ### Set your credentials

   Add your Scalekit credentials to your `.env` file. Find values in **[app.scalekit.com](https://app.scalekit.com)** > **Developers** > **API Credentials**.

   ```sh title=".env"
   SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
   SCALEKIT_CLIENT_ID=<your-client-id>
   SCALEKIT_CLIENT_SECRET=<your-client-secret>
   ```

3. ### Create the Mireye MCP connection

   In **AgentKit > Connections**, create a Mireye MCP connection and copy its redirect URI. The name you give it is the `connection_name` your code passes. See [Configure connections](/agentkit/connections/).

4. ### Register an OAuth app

   Mireye MCP server connections use your own OAuth app. Register one with Mireye MCP server and add the redirect URI you copied.

   Then enter the app's Client ID and Client Secret on the Mireye MCP connection.

5. ### Authorize a user and make your first call

   **Node.js** (`quickstart.mts`)

   ```typescript
   import { ScalekitClient } from '@scalekit-sdk/node'
   import 'dotenv/config'
   import { createInterface } from 'node:readline/promises'

   const scalekit = new ScalekitClient(
     process.env.SCALEKIT_ENVIRONMENT_URL,
     process.env.SCALEKIT_CLIENT_ID,
     process.env.SCALEKIT_CLIENT_SECRET,
   )
   const actions = scalekit.actions

   const connector = 'mireyemcp'
   const identifier = 'user_123'

   // Generate an authorization link for the user
   const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
   console.log('Authorize Mireye MCP:', link)
   const rl = createInterface({ input: process.stdin, output: process.stdout })
   await rl.question('Press Enter after authorizing...')
   rl.close()

   // Make your first call
   const result = await actions.executeTool({
     connector,
     identifier,
     toolName: 'mireyemcp_mireye_fetch',
     toolInput: {},
   })
   console.log(result)
   ```

   ```bash
   npx tsx quickstart.mts
   ```

   **Python** (`quickstart.py`)

   ```python
   import os
   from scalekit import ScalekitClient
   from dotenv import load_dotenv
   load_dotenv()

   scalekit_client = ScalekitClient(
       env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
       client_id=os.getenv("SCALEKIT_CLIENT_ID"),
       client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
   )
   actions = scalekit_client.actions

   connection_name = "mireyemcp"
   identifier = "user_123"

   # Generate an authorization link for the user
   link_response = actions.get_authorization_link(
       connection_name=connection_name,
       identifier=identifier,
   )
   print("Authorize Mireye MCP:", link_response.link)
   input("Press Enter after authorizing...")

   # Make your first call
   result = actions.execute_tool(
       tool_input={},
       tool_name="mireyemcp_mireye_fetch",
       connection_name=connection_name,
       identifier=identifier,
   )
   print(result)
   ```

   ```bash
   python quickstart.py
   ```

   Each user signs in once. See [Authorize a user](/agentkit/tools/authorize/) for the full flow and statuses.

## Tools

Pass the exact name to `execute_tool`, with an input like each tool's example. To ask for a tool that's missing, use the [request form](https://scalekitsupport.portal.usepylon.com/forms/request-a-connector-tool).

**Node.js**

```typescript
const result = await actions.executeTool({
  toolName: 'mireyemcp_mireye_ask',
  toolInput: {
    question: '<question>',
  },
  connector: 'mireyemcp',
  identifier: 'user_123',
})
```

**Python**

```python
result = actions.execute_tool(
    tool_name="mireyemcp_mireye_ask",
    tool_input={
        "question": "<question>",
    },
    connection_name="mireyemcp",
    identifier="user_123",
)
```

`result.data` is the app's response as JSON, and `result.execution_id` (`executionId` in Node.js) is the ID of the call.

### `mireyemcp_mireye_ask`

Ask Mireye · Read-only

Answer a location question with cited evidence for $0.10 per completed answer. Give
    coordinates or an address. Accept terms and reconnect to use licensed parcel evidence. Reuse
    a stable idempotency_key for retries; max_cost_usd is an optional dollar ceiling. Check
    geocode precision before treating an address answer as parcel-specific.

    Inspect parcel_grade and accuracy_type: range_interpolation is an estimate, not a
    rooftop match and can be about 2.9 km off in rural areas. State the precision_note
    before making parcel-specific claims.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `question` (`string`, required): Natural-language question about the coordinate.
- `address` (`string`, optional): No description.
- `idempotency_key` (`string`, optional): No description.
- `lat` (`string`, optional): No description.
- `lng` (`string`, optional): No description.
- `max_cost_usd` (`string`, optional): No description.

Example input: `{"question":"<question>"}`

### `mireyemcp_mireye_enrich`

Enrich a Parcel · Read-only

Enrich one US parcel with selected parcel attributes, point data and polygon calculations.
Give either address or lat+lng inside req. Fields and a list of Enrich presets combine by union;
omit both to request all Enrich fields. Prefer a small explicit selection. Call
mireye_list_fields with endpoint="enrich" for the Enrich catalog; Fetch has a
different field set. Inspect parcel_match.status first: only matched returns fields.
An address selects a parcel only from a rooftop-precision geocode; otherwise
parcel_match is no_match with a reason, and nothing is charged.
Never choose an ambiguous candidate automatically. Point data uses the parcel analysis
point; polygon calculations describe its boundary. Fields are sparse: omitted fields do not
establish a negative finding. Costs $0.02 per successful
parcel on Free, with paid-plan discounts; charged only when at least one requested field is
returned. Accept current terms and reconnect first. Use a stable idempotency_key for retries
and max_cost_usd for a dollar ceiling. An empty fields map, no-match, ambiguous and
unavailable results cost zero. At capacity it returns retryable enrich_busy.
Fields form a flat map in Enrich preset order, preserving each preset field order;
shared fields appear once at their first preset and unassigned fields follow in catalog order.
Each field contains value, source, confidence, interpretation_hints, and unit when available.
Failed fields are omitted. The fields map may be empty. Read hints before interpreting nulls.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `req` (`string`, required): No description.
- `idempotency_key` (`string`, optional): No description.

Example input: `{"req":"<req>"}`

### `mireyemcp_mireye_fetch`

Fetch Free Public Fields · Read-only

Fetch free public data fields at a US coordinate or address. Give either lat+lng or address. Each field includes its value, source, source URL, timestamp, confidence and status: ok, absent, or failed. Never treat a failed field as valid no-data; retry with backoff when retryable. Parcel identity, ownership, boundaries and parcel-dependent calculations require mireye_enrich. Presets contain only eligible public fields. Authentication, rate limits and capacity limits apply; Fetch never deducts from the dollar balance. An address result includes geocode quality; an estimated street location may describe a neighboring property.
    Inspect parcel_grade and accuracy_type: range_interpolation is an estimate, not a
    rooftop match and can be about 2.9 km off in rural areas. State the precision_note
    before making parcel-specific claims.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `address` (`string`, optional): No description.
- `fields` (`string`, optional): No description.
- `lat` (`string`, optional): No description.
- `lng` (`string`, optional): No description.
- `preset` (`string`, optional): No description.

Example input: `{}`

### `mireyemcp_mireye_field_request_status`

Poll a Mireye Field Request · Read-only

Poll the status of a field request filed with mireye_request_field: status, queue position, the promised estimated_ready_at (fixed at acceptance, never recomputed on poll), and -- once status is 'live' -- the resume call (a ready-to-send /v1/fetch request) that answers the original ask. Store request_id in durable task state, not conversation context: builds run on a scale of hours and the filing session will likely be gone before one finishes. Status vocabulary: 'received'/'screening' (still being screened; check waiting_on -- 'operator' means screening failed and a human has to look), 'matched' (the catalog already answered it, use resume), 'awaiting_confirm' (a near-miss or clarify needs you), 'rejected' (typed codes in disposition, terminal), 'queued'/'claimed'/'building'/'in_review'/'approved'/'publishing' (a build is in progress), 'live' (done, resume works now), 'blocked'/'expired' (terminal, no build). Requests are visible only to the credential that filed them; an id that doesn't exist -- or belongs to someone else -- is the same 404, never a 403 (a 403 would confirm the id exists).

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `request_id` (`string`, required): The request_id returned by mireye_request_field.

Example input: `{"request_id":"<request_id>"}`

### `mireyemcp_mireye_geocode`

Geocode a US Address · Read-only

Resolve a US street address to a coordinate, with the quality of that coordinate. Feed lat/lng to mireye_fetch or mireye_ask. ALWAYS check accuracy_type before trusting the result: 'rooftop' is on the parcel, but 'range_interpolation' is estimated along a street centerline and can be ~2.9 km out in rural areas — far enough to describe a neighbouring property instead. An address that can only be placed at a ZIP/city/county centroid is REJECTED as address_too_coarse rather than returned — if you get that, ask the user for a more complete address instead of retrying. The address you send is retained alongside the coordinate it resolves to, so a result can be audited later; pass lat/lng instead if that does not suit the caller.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `address` (`string`, required): US street address. Include a city+state or a ZIP — the upstream cannot place a bare street line.

Example input: `{"address":"<address>"}`

### `mireyemcp_mireye_list_fields`

List Mireye Fields · Read-only

List the field names a Mireye tool accepts, with type, unit, description, interpretation hints, null meaning and source. endpoint=fetch lists mireye_fetch fields and presets; endpoint=enrich lists mireye_enrich fields, presets and price; endpoint=search lists mireye_search names with filter_ops (operators allowed in filters; empty means output-only), returnable (allowed in fields) and price. Each tool has its own list: a name valid for one may be unknown to another. Use query to narrow by a case-insensitive substring of the name or description, for example query="flood". Free; never charged.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `endpoint` (`string`, required): Which tool's field list to return: fetch, enrich or search. One of: `fetch`, `enrich`, `search`.
- `query` (`string`, optional): Optional case-insensitive substring matched against names and descriptions.

Example input: `{"endpoint":"fetch"}`

### `mireyemcp_mireye_proximity`

Compute Drive-Time Distances · Read-only

Compute distance, nearest candidates, screening or labor sheds. Straight-line work and
    estimates are free; driving uses the active plan's per-calculation USD rate. Send
    max_cost_usd as a decimal string to bound spending and a stable idempotency_key for retries.
    Check resolved locations, geocode precision, unreachable legs and missing tracts. If you
    infer a missing city or substitute a coordinate, state that assumption to the caller.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `req` (`string`, required): No description.
- `idempotency_key` (`string`, optional): No description.

Example input: `{"req":"<req>"}`

### `mireyemcp_mireye_search`

Search Parcels · Read-only

Find the first parcels satisfying ALL conditions, not ranked top matches. Include state2 with eq or a nonempty in list of two-letter US state codes (50 states and DC). County is optional. Every filter is applied exactly, including geometry and calculated-field filters. Address filters match the parcel's recorded situs address. Point-sampled fields use the matched parcel's recorded latitude and longitude unchanged; a candidate without a valid recorded point is not checked and is reported in remarks. Each match returns identity plus one flat fields map: scalar filter values and every field named in fields, excluding information already represented by identity. fields accepts any public Enrich field, including parcel attributes and parcel calculations, plus the geometry outputs geometry, parcel_geometry_wkt and parcel_boundary_geojson. GET /v1/search/fields lists every name with its filter operators. Missing values remain null. Search costs $0.20 per completed query on Free, including valid zero matches and every requested field; active plan discounts apply. Each continuation page is a new query. Returns 10 matches per page by default, up to 100. next_cursor is the only signal that more pages may exist: null means this is the last page, and a short or empty page can still carry a cursor. Send next_cursor with unchanged filters and fields; page size and max_cost_usd may change. Use a new idempotency key for each page. remarks is always present and empty when the page is clean; each remark has a code and a message, and may add path, hint, candidates or matches. Branch on code and path only: time_limit_reached (the time limit cut this page short), source_unavailable (parcel data became unavailable partway through; returned matches are correct), candidates_not_checked (some candidates could not be checked, so a match may be missing) and field_unavailable (a requested field, named by path such as fields[0], could not be produced for some matches and is null there). Use max_cost_usd as a decimal-string ceiling and a stable idempotency key for retries. Absent values fail hard filters; a page with remarks cannot establish no-match. Point samples describe the point, not the entire parcel. Geometry filters use WGS84 GeoJSON Polygon/MultiPolygon and do not automatically return boundaries. Output describes the exact matched parcel. Each page has a 180-second time limit; allow at least 210 seconds on the client.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `req` (`string`, required): No description.
- `idempotency_key` (`string`, optional): No description.

Example input: `{"req":"<req>"}`

### `mireyemcp_mireye_request_field`

Request a New Mireye Field · Write

Ask Mireye for a data field it doesn't have yet, in plain language, at one or more example locations. If the catalog already answers it you get the value now with a citation (disposition 'matched_existing'/'partial') and never spend a build; if something close exists you get 'near_miss_confirm' to accept or reject; otherwise the field is queued to build and you get a request_id to poll with mireye_field_request_status. ALWAYS pass idempotency_key for agent-originated requests: the same key replays the existing request's state instead of filing a second build. Answering use_case/decision_threshold (what decision this feeds, and the value that flips it) is optional but sharply improves match quality and build speed. example_locations (1-10 entries) each carry exactly one of address, lat+lng, or polygon, plus optional claimed_value/note -- see docs.mireye.ai/api-reference/field-requests for the full entry shape. requested_fields optionally pre-splits a bundled ask into atomic sub-questions (plain-language asks); the server decomposes bundles anyway. extra carries the rarer structured fields verbatim (area_of_interest, expected_volume, freshness, constraints, known_sources, output_preference) -- same doc has their shapes. A 'rejected' disposition carries a typed rejection_code and routing_hint, never a bare no; a genuinely ambiguous location returns a stateless 'clarify' with candidates instead of guessing. Filing a field request is free; request and build capacity limits still apply.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `description` (`string`, required): Natural language. Say what the data IS, what decision it feeds, and what a good answer looks like.
- `example_locations` (`array`, required): No description.
- `callback_email` (`string`, optional): No description.
- `callback_webhook_url` (`string`, optional): No description.
- `context_blob` (`string`, optional): No description.
- `deadline` (`string`, optional): No description.
- `decision_threshold` (`string`, optional): No description.
- `extra` (`string`, optional): No description.
- `idempotency_key` (`string`, optional): No description.
- `requested_fields` (`string`, optional): No description.
- `use_case` (`string`, optional): No description.

Example input: `{"description":"<description>","example_locations":[]}`

## Related

Other Search connectors ([all 54](/agentkit/connectors/?category=search)):

- [Supadata](/agentkit/connectors/supadata/): Scalekit connector, API key, 21 tools
- [Exa](/agentkit/connectors/exa/): Scalekit connector, API key, 21 tools
- [Brave Search](/agentkit/connectors/brave/): Scalekit connector, API key, 18 tools


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
