# MentorCruise public MCP and machine API

Human guide (MCP setup, skills, matcher on the site):
https://mentorcruise.com/agents/

This file is the implementer spec. MentorCruise has a public MCP server at
`https://mentorcruise.com/mcp`. The assistant can search mentors, fetch
profiles, and after email verification apply and pay from credit balance.

Agent card payments use Stripe [Machine Payments Protocol (MPP)](https://docs.stripe.com/payments/machine/mpp)
and [Link Agent Wallet](https://link.com/agents). Charges settle to MentorCruise's
platform Stripe account and **top up credits**. We do not open a Stripe Connect
subscription on the agent's payment method.

This page is the public spec. Machine-readable copies:

| What | URL |
|---|---|
| MCP endpoint (Streamable HTTP) | `https://mentorcruise.com/mcp` |
| Server card (MCP registry / well-known) | `https://mentorcruise.com/.well-known/mcp.json` |
| Human guide | `https://mentorcruise.com/agents/` |
| This document (Markdown) | `https://mentorcruise.com/docs/mcp.md` |
| Short agent index | `https://mentorcruise.com/llms.txt` |
| Full agent index (this file) | `https://mentorcruise.com/llms-full.txt` |
| REST machine API | `https://mentorcruise.com/api/machine/` |

Registry name: `com.mentorcruise/public`. Transport: Streamable HTTP. MCP
protocol: `2025-03-26`. There is no public OAuth on this server; discovery tools
are anonymous, write tools use a mentee JWT.

## What it can do

- Find mentors by skill, role, language, budget, and response time.
- Show a profile: bio, skills, rating, starting price, response time.
- List plans and one-off sessions a mentor offers.
- Hand back a booking link with the right plan pre-selected.
- Ground recommendations in MentorCruise's actual categories.
- Register and verify a mentee account over email (browser Turnstile plus a
  6-digit code).
- Apply to a mentor with the user's own words, after verification.
- List open applications, read Pinax threads, reply, and withdraw when allowed.
- List open applications and pay accepted ones from credit balance.
- Book a one-off session from the chat (credits, then the chosen slot).
- Read and send TalkJS messages on an active mentorship or intro session.
- Book an intro call or a mentorship call when a slot is open.
- Top up credits with an MPP charge (Stripe shared payment token).
- Open the dashboard via a one-use signed-in browser URL.

## What it can't do

- Read the user's mailbox. The human has to open the verification page and
  pass the 6-digit code back.
- Skip the browser Turnstile check. A code alone does not create the account.
- Attach the agent's card to a mentor's Stripe Connect account. Payments land
  as credits on MentorCruise, and invoices are settled from that balance.
- Skip spam checks, email verification, or application rate limits.
- Reach the private Admin MCP at `/admin/mcp`. That endpoint is staff-only.

## Discovery

Clients should not need a hand-typed URL. Fetch any of:

```
GET https://mentorcruise.com/.well-known/mcp.json
GET https://mentorcruise.com/.well-known/mcp
GET https://mentorcruise.com/.well-known/mcp/server-card.json
GET https://mentorcruise.com/.well-known/ai-catalog.json
GET https://mentorcruise.com/llms.txt
```

`/.well-known/mcp.json` is a server card: reverse-DNS `name`, `remotes[]` with
`type: streamable-http`, plus `serverInfo` / `transport` for older parsers.

CORS is `Access-Control-Allow-Origin: *` on discovery, docs, MCP, and the
machine API.

`robots.txt` disallows `/mcp` (JSON-RPC is not a crawl target). `/agents/`
and `/llms.txt` are allowed and listed in the sitemap.

The MCP HTTP responses also send a `Link` header pointing at the server card
and this document.

## Setup

### Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "mentorcruise": {
      "transport": {
        "type": "streamable-http",
        "url": "https://mentorcruise.com/mcp"
      }
    }
  }
}
```

Restart Claude Desktop. In a new chat, type:
*"Find me a senior backend mentor under $250/month."*

### ChatGPT

On a Plus / Pro plan: **Settings → Connectors → Add → Custom MCP server**.

- **URL:** `https://mentorcruise.com/mcp`
- **Auth:** none (send a Bearer token later on write tools)

### Cursor

Edit `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "mentorcruise": {
      "url": "https://mentorcruise.com/mcp"
    }
  }
}
```

### VS Code

With the MCP extension installed, add to `settings.json`:

```json
"mcp.servers": {
  "mentorcruise": { "url": "https://mentorcruise.com/mcp" }
}
```

### Other clients

Any MCP client that supports **Streamable HTTP** works. Point it at
`https://mentorcruise.com/mcp` with no auth headers for discovery.

JSON-RPC initialize (optional smoke test):

```http
POST /mcp HTTP/1.1
Host: mentorcruise.com
Accept: application/json, text/event-stream
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "clientInfo": { "name": "example", "version": "1.0" }
  }
}
```

Then `tools/list`. Write tools that need a session send
`Authorization: Bearer <access>` on the same Streamable HTTP requests.

## Typical flows

### Search and recommend (no account)

1. `list_categories` if you need real category labels.
2. `search_mentors` with a short query (1–4 keywords; never the words
   "mentor" or "coach").
3. Show 2–3 results. Prefer mentors with reviews.
4. `get_mentor_profile` and `get_sessions_or_services` for the ones the user
   wants detail on.
5. For an ongoing plan: `create_booking_link`. For a one-off session after
   sign-in: `list_session_slots` then `book_session`. Do not route a one-off
   through `create_booking_link`.

### Apply and pay (verified mentee)

1. `register_mentee` with the user's email and name.
2. Human opens `verify_url`, completes Turnstile, pastes the 6-digit code.
   `verify_email`. Keep the `access` JWT as `Authorization: Bearer` on later
   calls.
3. `apply_to_mentor` with a real, specific `goal` (min 50 characters).
4. `list_applications` until `payable` is true.
5. `pay_application`. If credits are short, the tool returns `payment_required`
   with a `pay_url`. Pay that REST URL with an MPP credential, then retry.
6. `open_dashboard` when the human should see the thread in a browser.

### Messages and calls (verified mentee)

1. `get_application` for Pinax messages and `action_required`.
2. `send_application_message` to reply on an open application.
3. `withdraw_application` only when `can_withdraw` is true.
4. After mentorship or an intro session exists: `list_conversations`,
   `get_messages`, `send_message`.
5. Intro: `list_intro_call_slots` then `book_intro_call`. Mentorship call:
   `list_mentorship_call_slots` then `book_mentorship_call`.

REST mirrors the same functions under `/api/machine/`. MCP paid tools never
return HTTP 402 (JSON-RPC stays 200); they return a `payment_required` payload
that points at the REST `pay_url`.

## Authentication

Discovery tools (`search_mentors`, `get_mentor_profile`,
`get_sessions_or_services`, `create_booking_link`, `list_categories`) need no
account.

Write tools need a mentee JWT:

1. `POST /api/machine/register/` (or `register_mentee`) with `email`, optional
   `first_name`, `last_name`. We email a verification link and a 6-digit code.
   No mentee account is created until both the Cloudflare Turnstile check on
   that page and the code are confirmed. The response does not reveal whether
   the address already exists. It includes `verify_url`.
2. The human opens `verify_url` in a browser and completes Turnstile.
3. `POST /api/machine/verify/` (or `verify_email`) with `email` and `code`.
   If the browser check is missing, this returns `human_required` and the same
   `verify_url`. After both succeed: `access`, `refresh`, `mentee_id`,
   `mail_verified`.
4. Send `Authorization: Bearer <access>` on later MCP and REST calls.

Access tokens last 12 hours. Refresh with `POST /api/token/refresh/` and
`{"refresh": "<refresh>"}`. Refresh tokens last 7 days.

Write actions require `mail_verified=true`. An unverified JWT gets
`email_unverified`.

**Do not put the MPP Payment credential in `Authorization` when a Bearer token
is present.** Identity stays in `Authorization: Bearer`. The Stripe credential
goes in the `Payment` header (or JSON body `payment` / `credential`).

Dashboard links from `open_dashboard` / `GET /api/machine/dashboard/` are
one-use, expire in 30 minutes, and only redirect under `/mentee/`.

## MCP tools

### Discovery (anonymous)

#### `search_mentors`

Find mentors. Always call this before recommending anyone; do not invent names
from memory.

| Param | Type | Required | Notes |
|---|---|---|---|
| `query` | string | yes | 1–4 keywords. No "mentor" or "coach". Max 500 chars. |
| `skills` | list[str] | no | AND across groups, OR within. Hard filters only. |
| `industries` | list[str] | no | |
| `languages` | list[str] | no | Normalized (e.g. Spanish → español). |
| `tools` | list[str] | no | |
| `companies` | list[str] | no | |
| `budget_usd_monthly` | int | no | Monthly USD cap for ongoing mentorship. |
| `response_within_hours` | int | no | Max median response time. |

Returns up to 8 mentors, already ranked. `lowest_price_usd` is the cheapest
offering and may be a one-off or a monthly plan. Phrase as "starting at $X"
until `get_sessions_or_services` confirms cadence.

#### `get_mentor_profile`

| Param | Type | Required | Notes |
|---|---|---|---|
| `username` | string | yes | From search results. |

Public profile only. `{error: "not_found"}` if hidden or missing.

#### `get_sessions_or_services`

| Param | Type | Required | Notes |
|---|---|---|---|
| `username` | string | yes | |

`subscriptions[]` book via `/apply/` (`booking_route: apply`).
`one_off_sessions[]` book via `/sessions/.../book/` (`booking_route: session`).
Share the session `booking_url` as-is.

#### `create_booking_link`

Ongoing mentorship only.

| Param | Type | Required | Notes |
|---|---|---|---|
| `username` | string | yes | |
| `plan_hash` | string | no | From a subscription item. |
| `intent` | string | no | Passed through on the apply URL. |

Returns `apply_url`, `inquiry_url`, `requires_intro_call`. The user clicks
the link; this tool does not book.

#### `list_categories`

No params. Top-level category ids and labels for grounding search queries.

### Account (JWT)

#### `register_mentee`

| Param | Type | Required | Notes |
|---|---|---|---|
| `email` | string | yes | |
| `first_name` | string | no | |
| `last_name` | string | no | |

Returns `{status: "code_sent", verify_url, ...}`. Cooldown between sends.
The human must open `verify_url` and complete Turnstile before `verify_email`
will issue a token.

#### `verify_email`

| Param | Type | Required | Notes |
|---|---|---|---|
| `email` | string | yes | |
| `code` | string | yes | 6 digits. |

Returns Bearer `access` / `refresh` after Turnstile and the code. Otherwise
`human_required` with `verify_url`.

#### `get_account`

No params. Name, email, `credits_usd`, one-use `dashboard_url`.

#### `top_up_credits`

| Param | Type | Required | Notes |
|---|---|---|---|
| `amount_usd` | int | yes | Whole dollars, minimum 1. |

Without an MPP credential, returns `payment_required` with
`pay_url: https://mentorcruise.com/api/machine/credits/`. Pay that URL, then
retry the tool (or call the REST endpoint with the credential).

#### `open_dashboard`

| Param | Type | Required | Notes |
|---|---|---|---|
| `kind` | string | no | `applications` (default), `home`, or `mentorship`. |
| `mentorship_hash` | string | if kind=mentorship | From `list_mentorships`. |

### Applications (JWT)

#### `apply_to_mentor`

| Param | Type | Required | Notes |
|---|---|---|---|
| `username` | string | yes | Public mentor slug. |
| `goal` | string | yes | Min 50 characters. Must be specific to this mentor. |
| `introduction` | string | no | About the mentee. Same length rules if sent. |
| `service_expectations` | string | no | What they want from the mentor. |
| `mentee_question` | string | no | Optional question for the mentor. |
| `first_name` / `last_name` | string | no | Falls back to the account name. |
| `plan_hash` | string | no | Must belong to this mentor. |
| `timezone` | string | no | Default `UTC`. |
| `user_info` | int | no | See table below. |
| `timeline` | int | no | See table below. |
| `time_expectations` | int | no | See table below. |

Does not charge. The mentor is notified after a spam check.

`user_info`: 0 undisclosed, 1 student, 2 recent graduate, 3 career change / new
job, 4 skill growth, 5 personal project, 7 business / product.

`timeline`: 0 none, 1 a few weeks, 2 about a month, 3 about three months,
4 about six months, 5 a year or more.

`time_expectations`: 0 none, 1 instant, 2 a few hours, 3 within a day,
4 a few days.

#### `list_applications`

Open applications (`draft`, `new`, `pending`, accepted-and-unpaid). Use
`pay_application` when `payable` is true.

#### `pay_application`

| Param | Type | Required | Notes |
|---|---|---|---|
| `application_hash` | string | yes | From `list_applications`. |

Pays from credit balance. Shortfall → `payment_required` with
`pay_url: https://mentorcruise.com/api/machine/applications/<hash>/pay/`.
Paying that URL tops up (if needed) and completes the mentorship. We still do
not create a Connect subscription on the agent's method.

#### `list_mentorships`

Active mentorships plus dashboard URLs.

#### `get_application`

| Param | Type | Required | Notes |
|---|---|---|---|
| `application_hash` | string | yes | From `list_applications`. |

Status, `action_required`, `can_withdraw`, Pinax `messages`.

#### `send_application_message`

| Param | Type | Required | Notes |
|---|---|---|---|
| `application_hash` | string | yes | |
| `content` | string | yes | No scheduling links. |

#### `withdraw_application`

| Param | Type | Required | Notes |
|---|---|---|---|
| `application_hash` | string | yes | Only when `can_withdraw` is true. |

Destructive. Cannot be undone.

#### `list_conversations` / `get_messages` / `send_message`

TalkJS threads for active mentorships and intro sessions. `conversation_id`
is the hash from `list_conversations`. Pre-mentorship Pinax threads stay on
`get_application`.

#### `list_intro_call_slots` / `book_intro_call`

Only after the mentor accepts and the intro call is not yet scheduled.

#### `list_mentorship_call_slots` / `book_mentorship_call`

Needs an active mentorship with a Cal event. External calendar links return
`not_available` plus `calendar_link`.

#### `list_session_slots` / `book_session`

| Param | Type | Required | Notes |
|---|---|---|---|
| `setup_id` | int | yes | From `get_sessions_or_services` `one_off_sessions[].id`. |
| `start` | string | yes on book | ISO-8601 from `list_session_slots`. |

`book_session` charges credits (MPP top-up if short) then books the Cal slot.

## REST machine API

Base: `https://mentorcruise.com/api/machine/`

`GET /api/machine/` returns this index as JSON.

| Method | Path | Auth | Payment |
|---|---|---|---|
| GET | `/api/machine/` | no | |
| POST | `/api/machine/register/` | no | body: `email`, `first_name`, `last_name` |
| POST | `/api/machine/verify/` | no | body: `email`, `code` |
| GET | `/api/machine/me/` | Bearer | account + credits + dashboard URL |
| POST | `/api/machine/credits/` | Bearer | 402 MPP; body `amount_usd` |
| GET | `/api/machine/applications/` | Bearer | list |
| POST | `/api/machine/applications/` | Bearer | apply; 201 |
| POST | `/api/machine/applications/<hash>/pay/` | Bearer | credits, else 402 |
| GET | `/api/machine/mentorships/` | Bearer | |
| GET or POST | `/api/machine/dashboard/` | Bearer | `kind`, `mentorship_hash` |
| POST | `/api/machine/sessions/book/` | Bearer | body: `setup_id`, `start`; 402 MPP if credits are short |

Apply body matches `apply_to_mentor`. CORS allows headers
`Authorization, Content-Type, Payment, Mpp-Receipt`. Successful MPP responses
echo `Mpp-Receipt`.

### curl: register, verify, apply

```bash
curl -sS -X POST https://mentorcruise.com/api/machine/register/ \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","first_name":"Ada","last_name":"Lovelace"}'

curl -sS -X POST https://mentorcruise.com/api/machine/verify/ \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","code":"123456"}'
# save .access

curl -sS -X POST https://mentorcruise.com/api/machine/applications/ \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{"username":"mentor-slug","goal":"I am a backend engineer moving toward staff..."}'
```

### curl: 402 then pay with MPP

```bash
# First call: no Payment header → HTTP 402 + WWW-Authenticate: Payment ...
curl -i -X POST https://mentorcruise.com/api/machine/credits/ \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{"amount_usd":25}'

# Retry with the Stripe shared payment token (Link Agent Wallet / MPP client).
# Keep Bearer for identity. Put the credential on Payment, not Authorization.
curl -sS -X POST https://mentorcruise.com/api/machine/credits/ \
  -H "Authorization: Bearer $ACCESS" \
  -H "Payment: $MPP_CREDENTIAL" \
  -H 'Content-Type: application/json' \
  -d '{"amount_usd":25}'
```

The JSON body may send `"payment": { ...credential... }` instead of the header.
Minimum charge is **$1 USD** (credits are whole dollars; Stripe SPT floor is
$0.50). Challenges expire in 10 minutes and are bound to the mentee.

MPP / SPT overview: [Stripe machine payments](https://docs.stripe.com/payments/machine),
[MPP](https://docs.stripe.com/payments/machine/mpp),
[Link agents](https://link.com/agents).

## Errors

Tools return `{ "error": "<code>", "message": "..." }` inside a successful
JSON-RPC response. REST uses the same body with HTTP 4xx/402/5xx.

| Code | Meaning |
|---|---|
| `auth_required` | Send `Authorization: Bearer` from `verify_email`. |
| `email_unverified` | Finish `verify_email` before write actions. |
| `human_required` | Open `verify_url` in a browser and complete Turnstile, then retry `verify_email`. |
| `invalid_email` / `invalid_code` | Check the address or 6-digit code. |
| `invalid_input` | Text too short, name invalid, or spam heuristics. |
| `not_found` | Unknown mentor, application, or mentee. |
| `already_applied` | Open application already exists for that mentor. |
| `already_mentoring` | Active mentorship already exists. |
| `mentor_full` | No open spots. |
| `rejected` | Application failed spam / reuse checks. Write a unique message. |
| `rate_limited` / `rate_limit_exceeded` | Wait and retry. |
| `payment_required` | Pay `pay_url` with MPP, then retry. |
| `invalid_payment` | Credential present but could not be settled. |
| `invalid_plan` | `plan_hash` does not belong to that mentor. |
| `not_available` | Withdraw, booking, or messaging is closed for this object. |
| `slot_unavailable` | The chosen Cal slot was taken. List slots again. |
| `booking_unknown` | Cal timed out or returned nothing. Do not pick another slot until you check. |
| `empty_message` | Message body was blank. |
| `scheduling_link_blocked` | Application messages cannot include calendar links. |

## Rate limits

| Layer | Limit |
|---|---|
| HTTP on `/mcp` | 120 requests / min / IP |
| `search_mentors` | 30 / min / IP |
| Other discovery tools | 60 / min / IP |
| `register_mentee` / `apply_to_mentor` | 10 / min / IP, plus account-level application caps |
| Other authenticated write tools | 20–30 / min / IP |
| Send / book / withdraw | also 10–20 / hour / mentee |
| REST register | 10 / hour / IP |
| REST verify | 30 / hour / IP |
| REST apply / pay / credits / session book | 20 / hour / user |

Verification emails also have per-address and per-IP send caps. Hitting a tool
limit returns `rate_limit_exceeded` without dropping the MCP session.

## Privacy

- Discovery is anonymous. Search and profile tools need no account.
- Applying and paying require a mentee account. We email a verification code
  to the address you give us. The assistant never sees a password; we set a
  random one.
- Per request we store a one-way hash of the IP and which tools ran, for abuse
  prevention and product analytics. We do not log full query text beyond a
  truncated search keyword.
- Mentor emails, Stripe Connect ids, payout internals, and admin flags are
  never returned.

## Try a prompt

> I'm an L4 backend engineer at a Series B startup, looking to transition
> into staff/principal. Find me 3 mentors who've done that, prefer ones in
> European timezones, budget around $250/month, and give me booking links.

After setup, the assistant should call MentorCruise tools and return results
with clickable links. To apply in-band: ask it to register your email, open
the verification link, complete the check, then paste the 6-digit code.

## Troubleshooting

- **"No mentors found."** Broaden: fewer skill filters, no budget cap, no
  timezone preference. Prompt: *"Try again with no budget filter."*
- **"Tool unavailable / rate limit."** Wait a minute and retry.
- **Tool list is empty.** The client must support Streamable HTTP (not
  SSE-only or stdio-only). Restart after editing config.
- **`auth_required` on apply/pay.** Call `register_mentee` → `verify_email`,
  then send the Bearer token on the next MCP request.
- **`payment_required` in MCP.** JSON-RPC will still be HTTP 200. Read
  `pay_url` and `challenge`, settle via REST with the `Payment` header, retry.
- **402 on REST with a Bearer token.** The MPP credential is missing or in the
  wrong header. Keep Bearer; put Payment on `Payment`.
- **Dashboard link 400 on second open.** It is one-use. Call `open_dashboard`
  again.

## Feedback

info@mentorcruise.com
