# 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`. Discovery tools are anonymous. Write tools use OAuth 2.1 (PKCE S256, dynamic client registration) or a mentee JWT. Hosted clients complete Connect; the host then sends `Authorization: Bearer`. ## 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. Connect completes email + Turnstile + the 6-digit code in the browser. The in-chat fallback still needs the human to open `verify_url` and pass the code back to the assistant. - 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/.well-known/oauth-protected-resource GET https://mentorcruise.com/.well-known/oauth-authorization-server 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 Custom connector (claude.ai, Cowork, Claude Desktop): **Customize → Connectors → + → Add custom connector**. Name: MentorCruise. URL: `https://mentorcruise.com/mcp`. - **Authentication:** Required when the server asks (anonymous search, OAuth on write tools). - **OAuth client:** No client ID. We support Dynamic Client Registration and Client ID Metadata Documents (CIMD). Claude Code uses CIMD plus a loopback redirect; hosted Claude uses `https://claude.ai/api/mcp/auth_callback`. When you apply, complete Connect in the browser. The host then sends `Authorization: Bearer`. Local Desktop config still works. 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 Install the published plugin: https://chatgpt.com/plugins/plugin_asdk_app_6a28f1ae232c819195f8a8faec6c255c Search works without signing in. When you apply, complete Connect in the browser. The host then sends `Authorization: Bearer` on later calls. Custom / Developer mode: Settings → Security and login → Developer mode, then [ChatGPT Plugins](https://chatgpt.com/plugins) → **+**. Connection: Server URL `https://mentorcruise.com/mcp`. Authentication: OAuth. Check **I understand and want to continue**, then Create. ### 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`. Search and other discovery tools work with no token. Hosted clients must not require Connect before `search_mentors`. Write tools still need a Bearer token (OAuth Connect or `verify_email`). 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`. The anonymous list is the full public catalog (discovery + account + applications + messaging + booking). Write tools still require a Bearer token at call time. Hosted clients attach it after Connect. Without a token, write `tools/call` returns HTTP 401 with `WWW-Authenticate` pointing at `https://mentorcruise.com/.well-known/oauth-protected-resource`, plus `{error: "auth_required", message: "..."}`. That is not a missing-tool error. `initialize`, `tools/list`, and discovery tools stay HTTP 200 with no `WWW-Authenticate`. ## 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`. **MCP clients and MPP:** HTTP clients retry `pay_url` with a `Payment:` header or JSON `payment` field. MCP tool calls cannot attach HTTP headers. Pass an optional `payment_credential` argument on `top_up_credits`, `pay_application`, and `book_session` when the host wallet provides a Stripe shared payment token. Otherwise call `open_dashboard` and pay in the browser, then retry the tool. Claude Code does not ship an agent wallet today — use the browser fallback. ## Authentication Discovery tools (`search_mentors`, `get_mentor_profile`, `get_sessions_or_services`, `create_booking_link`, `list_categories`) plus `register_mentee` / `verify_email` need no account. Every public tool is still advertised on `tools/list`. ### OAuth (hosted clients) MCP Authorization (OAuth 2.1). Metadata: - `GET /.well-known/oauth-protected-resource` - `GET /.well-known/oauth-protected-resource/mcp` - `GET /mcp/.well-known/oauth-protected-resource` - `GET /.well-known/oauth-authorization-server` PKCE `S256` is required. Dynamic client registration is `POST /oauth/register`. Client ID Metadata Documents are also supported (`client_id_metadata_document_supported: true`). Loopback redirects (`http://localhost/callback`, `http://127.0.0.1/callback`) match with the port ignored, so Claude Code's ephemeral callback port works. Register every `redirect_uris` value the client sends, including custom schemes such as `cursor://anysphere.cursor-mcp/oauth/callback` and `https://www.cursor.com/agents/mcp/oauth/callback`. Authorize accepts the registered URI, or the same loopback URI with a different port. `GET /oauth/authorize` signs in an existing mentee session or completes email + Turnstile + a 6-digit code **in the browser**. `POST /oauth/token` returns `access_token` / `refresh_token` (the same mentee JWTs as `verify_email`). The host then sends `Authorization: Bearer`. ### In-chat JWT (fallback) Write tools also accept a mentee JWT from this flow: 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 ` on later MCP and REST calls. Access tokens last 12 hours. Refresh with `POST /oauth/token` (`grant_type=refresh_token`) or `POST /api/token/refresh/` and `{"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//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//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": "", "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