# Quickstart

Nothing to install. Three steps, and the third returns real postings.

## 1. Get in

Give your client the endpoint and sign in when it asks. It registers itself —
no client id, no secret, nothing to paste. Claude and ChatGPT both do this.

If your client cannot run an authorization flow, mint a token at
[/connect](/connect) and paste that instead. Both ways land on the same account:
one plan, one trial, one history.

```
https://buyer.moxlade.com/mcp/
```

The trailing slash matters: without it you get a redirect, and a client that
does not replay a POST body across one fails in a way that looks like our bug.

## 2. Prove it works

`get_plan` takes no arguments, costs nothing against your caps, and answers on
every plan state — so it tells you the connection is good without spending
anything.

```json
{
  "name": "get_plan",
  "arguments": {}
}
```

```json
{
  "plan": "paid",
  "state": "active",
  "trial_ends_at": null,
  "price_usd_month": 49,
  "billing": "flat monthly, no credits, no per-call fee",
  "saved_searches": "matching",
  "subscribe": null,
  "manage_or_cancel": "write to support@moxlade.com",
  "label": "glama-sandbox",
  "usage": {
    "calls_today": 45,
    "daily_call_cap": 500,
    "distinct_corpus_questions_today": 3,
    "daily_distinct_corpus_question_cap": 120,
    "resets_at": "UTC midnight",
    "note": "repeating a corpus question you already asked today does not spend another distinct question; it still spends a call."
  }
}
```

*Synthetic sandbox data — the shape is production's, the numbers are not.*

You should get your plan, its state, and `usage` — today's calls against the
daily cap. If instead you get a `401`, the token is wrong or missing; see
[refusals](/docs/refusals), which explains why there are two different ones.

## 3. Your first real question

Same envelope, a different tool. This searches the live corpus:

```json
{
  "name": "search_jobs",
  "arguments": {
    "query": "Django",
    "limit": 3
  }
}
```

```json
{
  "count": 3,
  "matched": 3,
  "capped_at": 3,
  "window_days": 90,
  "jobs": [
    {
      "upwork_id": "sbx01",
      "title": "<untrusted-scraped-content>Senior Django engineer for an internal analytics API</untrusted-scraped-content>",
      "description": "<untrusted-scraped-content>We need a Django REST API over an existing warehouse. Long term, part time.</untrusted-scraped-content>",
      "url": "https://example.invalid/j/sbx01",
      "date_posted": "2026-09-02T14:47:39.986313+03:00",
      "skills": "Django, Python, PostgreSQL",
      "price_type": "HOURLY",
      "price": null,
      "price_min": 55,
      "price_max": 80,
      "category_name": "Web, Mobile & Software Dev",
      "subcategory_name": "Back-End Development",
      "client_location": "Germany",
      "total_spent": 412000,
      "avg_hourly_rate": 62,
      "buyer_payment_verified": true,
      "client_total_hired": 61,
      "client_total_applicants": 12
    },
    {
      "upwork_id": "sbx02",
      "title": "<untrusted-scraped-content>Django + HTMX dashboard, 3 week engagement</untrusted-scraped-content>",
      "description": "<untrusted-scraped-content>Replace a spreadsheet workflow with a small internal dashboard.</untrusted-scraped-content>",
      "url": "https://example.invalid/j/sbx02",
      "date_posted": "2026-08-30T14:47:39.986313+03:00",
      "skills": "Django, HTMX, Tailwind",
      "price_type": "FIXED",
      "price": 4200,
      "price_min": null,
      "price_max": null,
      "category_name": "Web, Mobile & Software Dev",
      "subcategory_name": "Full Stack Development",
      "client_location": "United States",
      "total_spent": 1870000,
      "avg_hourly_rate": 48,
      "buyer_payment_verified": true,
      "client_total_hired": 148,
      "client_total_applicants": 31
    },
    {
      "upwork_id": "sbx08",
      "title": "<untrusted-scraped-content>Small Django bug fix, one afternoon</untrusted-scraped-content>",
      "description": "<untrusted-scraped-content>A migration is failing on deploy. We have the traceback.</untrusted-scraped-content>",
      "url": "https://example.invalid/j/sbx08",
      "date_posted": "2026-07-28T14:47:39.986313+03:00",
      "skills": "Django, Python",
      "price_type": "FIXED",
      "price": 250,
      "price_min": null,
      "price_max": null,
      "category_name": "Web, Mobile & Software Dev",
      "subcategory_name": "Back-End Development",
      "client_location": "Portugal",
      "total_spent": 22000,
      "avg_hourly_rate": 51,
      "buyer_payment_verified": true,
      "client_total_hired": 12,
      "client_total_applicants": 6
    }
  ]
}
```

*Synthetic sandbox data — the shape is production's, the numbers are not.*

Read `result.structuredContent`: `matched` is how many postings exist for that
phrase, `jobs` is the page you got, and `next_cursor` is there while more
remain. Those postings are now in your **feed**, which is what lets `get_buyer`
and `get_buyer_quality` answer about them.

## Where to go next

- [Workflows](/docs/workflows) — the six sequences, with call order and cost. Start here if you know what you want to accomplish.
- [Filter reference](/docs/filters) — the filter language, if a phrase is not precise enough.
- [Tool reference](/docs/tools) — all 15 of them, with arguments and result fields.
- [Example prompts](/docs/prompts) — if you would rather just ask your agent.
