mcp-server-splitmygear
OfficialProvides Continue with Apple as an OAuth sign-in option for Splitt users connecting MCP clients.
Provides Continue with Google as an OAuth sign-in option for Splitt users connecting MCP clients.
Integrates with Stripe for payments and vendor payouts: booking tools return Stripe-hosted Checkout payment URLs, and vendor tools expose Stripe Connect status and onboarding.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-server-splitmygearfind a 4-person tent for this weekend in Seattle"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-server-splitmygear
The official MCP (Model Context Protocol) server for Splitt, the outdoor gear rental marketplace. It lets AI assistants (ChatGPT, Claude, Cursor, Windsurf, custom agents) act for Splitt renters and vendors: search and book gear and experiences, manage bookings, message the other party, list and price gear, run a vendor's calendar and see payouts. Everything a person can do in the Splitt web app that makes sense for an agent, with the same permissions.
219 tools, filtered by who is signed in and what they granted (see docs/mcp-tools.md)
Sign in with your Splitt account from any OAuth-capable MCP client (OAuth 2.1 + PKCE; email one-time-code 2FA; Continue with Google / Apple)
Scoped access: clients may request a subset of 12 scopes (
read profile bookings favorites messaging reviews listings vendor_bookings experiences finance claims files); the sign-in page shows exactly what the app will be able to do, and tools outside the granted scopes are neither listed nor callableThin, stateless client of the Splitt backend REST API: no database or payment credentials live here (ADR 0001, ADR 0002)
Production endpoint: https://mcp.go-splitt.com/mcp
Connect
As a Splitt user (renter or vendor)
Add the server URL to any MCP client that supports OAuth (ChatGPT developer mode, Claude.ai and Claude Desktop connectors, Cursor, Windsurf, the MCP Inspector). The client discovers the sign-in flow automatically, opens the hosted Splitt sign-in page, and from then on every tool acts as you.
{
"mcpServers": {
"splitt": { "url": "https://mcp.go-splitt.com/mcp" }
}
}Enter the URL exactly as above (https://mcp.go-splitt.com/mcp, no trailing slash): Claude compares it with the resource this server advertises.
Claude (claude.ai, Desktop, mobile): Customize → Connectors → + → Add custom connector, paste the URL, Add, then Connect on the connector and sign in. Team and Enterprise owners add it under Organization settings → Connectors → Add → Custom → Web; members then Connect it themselves. Leave the OAuth client ID and secret under Advanced settings empty: Claude registers itself.
Claude Code:
claude mcp add --transport http splitt https://mcp.go-splitt.com/mcp, then run/mcpand choose Authenticate.ChatGPT (Plus, Pro, Business, Enterprise, Edu, on the web): turn on Settings → Security and login → Developer mode, open Plugins, press + to create an app for a remote MCP server, paste the URL and choose OAuth. ChatGPT asks you to confirm every tool that is not read-only.
What the sign-in page does: your email and password go straight to Splitt's own login API (this server never stores them); if two-step verification is on, you enter the emailed code; the client receives short-lived tokens that wrap your Splitt session. Signed up with Google or Apple? Use the Continue with Google / Continue with Apple buttons (shown when Splitt has that provider configured): the round trip runs through Splitt's own provider login and ends back here, which then issues the client its code exactly as after a password sign-in. Two-step verification applies to social sign-in too.
As an operator (server-to-server, public tools only)
{
"mcpServers": {
"splitt": {
"url": "https://mcp.go-splitt.com/mcp",
"headers": { "x-api-key": "your-operator-key" }
}
}
}The operator key unlocks the public tools (search, details, availability, calendar, quotes, reviews, market pricing, experiences). It cannot act as a user.
Or over plain HTTP:
curl -X POST https://mcp.go-splitt.com/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: $MCP_API_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_listings",
"arguments": { "query": "tent for a family camping trip this weekend" }
}
}'With an existing Splitt session token
A first-party integration that already holds a backend JWT (from POST /api/v1/users/login) may send it as Authorization: Bearer <jwt>. The token is VERIFIED before it authenticates, never decoded and trusted (SPLIT-1438): in-process against MCP_BACKEND_JWT_SECRET (the backend's JWT_SECRET) when that is configured, otherwise by asking the backend itself who the caller is (GET /users/profile, the same authority every tool forwards to, cached for 60s). Both paths fail closed — a forged, expired or unverifiable JWT is rejected. The secret changes the SPEED of bearer auth, never its strength.
Claude Desktop Extension
Install manifest.json through the Extension Manager. Leave the API key empty to sign in as a user, or fill it in for operator access.
Related MCP server: Mountaineers MCP Server
What you can do
The tool list a client receives already reflects the signed-in account and the granted scopes, so the model is never offered tools it cannot use.
Who | Tools | Highlights |
Anyone (operator key or user) | 24 | search, listing details, availability calendar, price quotes, reviews, market pricing, experiences and services, public routes, destinations, categories, trip planning |
Signed-in user | +89 | profile and security settings, notifications, bookings (list, cancel with refund preview, reschedule responses, protection plan), pickup/return photos and inspection checklists, reviews, favorites, saved searches and trips, conversations and messages, experience and service bookings, waivers, disputes, damage-claim responses, incidental charges, evidence uploads, trust score, vendor onboarding, AI drafting helpers |
Renter | +2 |
|
Vendor seat ( | +98 | listings (create, update, publish, duplicate, delete, AI draft, performance), blackout dates, seasonal rate rules and dynamic pricing, fleet units, calendar feeds and iCal, routes and GPX import, insurance and waivers, message templates, incoming bookings, overdue / return status, reschedule proposals, private notes, damage claims and incidental charges, review responses, dashboard, experiences hosting, services, promotions, auto-approve, report subscriptions, tax summary |
Vendor owner | +6 |
|
Full reference with every argument: docs/mcp-tools.md (generated from the code by npm run gen:docs).
Payments never happen inside the MCP: booking tools return a Stripe-hosted paymentUrl for the person to open. Money, availability, pricing, ownership and permissions are all decided by the Splitt backend on every call.
Security model
Deny by default. No credential, no service. A 401 carries
WWW-Authenticatewith the RFC 9728 resource-metadata URL so OAuth clients can start sign-in. Raw backend JWTs are verified before they authenticate — in-process againstMCP_BACKEND_JWT_SECRETwhen it is set, otherwise against the backend itself (GET /users/profile, identity taken from the backend's answer, never from the client's claims); an unverifiable bearer is rejected, never decoded and trusted (SPLIT-1438). OAuth tokens prove their own provenance: the backend JWT inside a sealed envelope is the one this server received from the backend, so it is only decoded, and nothing in the request middleware ever decodes without verifying.GET/DELETEon the MCP endpoint (/mcpand/api/mcpboth always answer; seeMCP_RESOURCE_PATHbelow) answer 405 (stateless transport).The backend is the authority. Every user-scoped call forwards the user's own Splitt JWT; the backend re-validates it and enforces role, ownership and lifecycle rules. This server never accepts a caller-supplied user id.
Scopes. Every tool belongs to one OAuth scope (see the Scopes table in docs/mcp-tools.md). Clients request scopes with the standard space-separated
scopeparameter on/oauth/authorize; a client that sends none is granted all scopes and the consent page says so in plain words. Thescopemember of the token response echoes the grant. Arefresh_tokenrequest may passscopeto narrow the grant (never widen it), and the narrowed set persists in the new refresh token. The operator API key hasreadonly; a verified raw backend JWT has every scope. Scopes never override the backend role model: grantinglistingsto a renter account unlocks nothing, and the backend re-checks every forwarded call.Stateless OAuth. Authorization codes, access tokens, refresh tokens, registered client ids and in-flight sign-in requests are AES-256-GCM envelopes sealed with
MCP_OAUTH_SIGNING_KEY(purpose-bound keys, so a code can never be replayed as a token). PKCE S256 is mandatory; onlyhttpsor loopback redirect URIs register; codes live 2 minutes and are single-use. Every redirect back to the app, success or error, carriesiss(RFC 9207), and the metadata says so. Loopback redirects match on any port (RFC 8252 §7.3), which Claude Code needs: it registershttp://localhost/callbackand returns on a new port every session; https redirects match exactly.resource(RFC 8707) may name the MCP endpoint or this origin, with or without a trailing slash; any other resource isinvalid_target.Refresh without surprise disconnects. Refreshing rotates the Splitt session, so a refresh cannot simply be retried. For 60 seconds after a rotation, the same refresh token presented again by the same app (a retry after a dropped response, or two requests that refreshed at once) gets the same new tokens instead of
invalid_grant. Concurrent repeats on one instance wait for the rotation in progress; across instances the answer is kept in the shared store as ciphertext that only the presented refresh token (together with this server's secret) can decrypt. A failed refresh is never kept.Your password is never stored. The hosted sign-in page relays it once to Splitt's login API, together with your real IP via the backend's trusted relay header (
MCP_BFF_RELAY_KEY) so Splitt's brute-force throttling keys on you, not on this server. The form only accepts same-origin submissions (a hostile page cannot drive it with its visitors' browsers). A rejected password is answered with one fixed message that says nothing about whether the address is registered.Sign-in throttling, and what it deliberately does not do. Failed attempts are counted per IP and per account, 10 per 10 minutes; the count is consumed atomically as part of the check, so a burst of simultaneous guesses cannot slip past the ceiling together. A successful sign-in gives its slot back and never resets the budget. The two counters are enforced at different moments, on purpose: the per-IP one refuses an attempt up front, while the per-account one is consulted only after the backend has already rejected the credentials. That ordering is what stops a stranger who knows your email address from locking you out of MCP sign-in by submitting wrong passwords for you (CWE-645) — your correct password returns before the account counter is ever read. The trade-off is real and worth stating: the per-account counter no longer keeps a password-spray away from the backend, only from succeeding. Splitt's own per-IP and per-email throttles — which see your real address, not this server's — are the authoritative control, and they use the same ordering (SPLIT-427).
Social sign-in cannot skip the consent card. Continue with Google / Apple can only be started by a click on the sign-in page itself (the start route requires a same-origin navigation), and the browser that clicked is tied to the return trip by a nonce carried in the sealed request and in a short-lived HttpOnly cookie; the callback refuses anything else. The one-time exchange code the backend hands back is swapped once and expires after a minute. The backend must list this server's callback in
SOCIAL_AUTH_RETURN_ORIGINS(pin the path:https://<this host>/oauth/social/callback) or it will not send the browser back here.Phishing resistance. Registration is closed by default: an
httpsredirect URI may register only if it is on the operator allow-list (MCP_OAUTH_ALLOWED_REDIRECT_HOSTS), so an unset variable permits nothing rather than everything, and registration fails with an error naming the variable. Entries may pin a path, and production pins each client's documented callback: the redirect must then be that path, or that path followed by plain segments (letters, digits,-._~, no dot segments), on the default port with no query or user info, so no other page on an allowed host can receive a code. User info is refused on every redirect URI. Loopback (http://localhost,127.0.0.1,[::1]) is always allowed. The list is re-checked on every use of a client id, not just at registration, so tightening it immediately invalidates ids already issued under a looser policy. The token endpoint re-checks it too, so removing a host also stops existing connections from redeeming codes or refreshing. The sign-in page shows the app's name and the exact address it will send you to. (It would label an app "unverified" if its redirect host were not allow-listed, but registration already requires that, so in practice only a client resolved while the list is being narrowed mid sign-in can show it.) Proxy headers are only trusted on Vercel or withMCP_TRUST_PROXY_HEADERS=1.Hardened responses. Strict CSP on the sign-in page (no scripts, no remote assets;
form-actionallows this origin plus the validated redirect origin of the sign-in request, because browsers apply it to the redirect that follows the form),Referrer-Policy: same-originthere so the form's own POST carries a realOrigin,no-storeeverywhere,X-Frame-Options: DENY, HSTS, constant-time secret comparison, sanitized error messages. The sign-in page names the app and the host the browser returns to above the form, and adds a warning when that is a program on the user's own computer (a loopback redirect), as the MCP authorization spec asks.Results sized for the assistant. Tool results are compact JSON capped at 60,000 characters (Claude Code stops at 25,000 tokens per result by default, claude.ai at about 150,000 characters). An oversized result keeps its largest list shortened to what fits and says so in
resultTruncated(field, returned, total, how to narrow).Model safety. Destructive tools carry MCP
destructiveHint; tools that return other users' text (listings, messages, reviews, calendar feeds) say in their description that it is data, not instructions, and the server instructions repeat it; server instructions tell the model to confirm cancellations and never collect card numbers.Rate limiting: two budgets, charged per invocation. Every principal has a per-minute budget of HTTP requests AND a separate one of tool invocations (SPLIT-1449). A JSON-RPC batch is charged per
tools/callmember, all-or-nothing — one POST cannot buy N invocations for the price of one, and a refused batch consumes nothing — and the 429 says which ceiling was hit. Both budgets share one principal key (verified user id, or the caller's address on the operator key) in disjoint key spaces, so neither can exhaust the other.Rate limiting and throttles across instances. With a shared store configured (
UPSTASH_REDIS_REST_URL/UPSTASH_REDIS_REST_TOKEN, or the Vercel KV names), the per-principal MCP rate limit, the sign-in failure throttle (10 failures per 10 minutes per IP and per account) and the authorization-code single-use cache are enforced across every serverless instance. Without one they are per-instance — which on Vercel means per concurrent lambda, and a distributed attacker simply outruns them. That degradation is allowed but never silent: each affected path logs a startup warning naming all three protections, once per instance. It is allowed rather than fatal because failing closed on a paid dependency would take the only user-facing sign-in path offline, while the two controls that actually stand between an attacker and an account — Splitt's own throttles (fed your real IP) and mandatory PKCE S256 on every authorization code — are unaffected by it. An operator who wants the strict posture instead setsMCP_REQUIRE_SHARED_STORE=1, and OAuth then refuses to enable at all until a store is configured.
Report security issues to security@go-splitt.com.
Running locally
git clone https://github.com/SplitMyGear/mcp-server-splitmygear
cd mcp-server-splitmygear
npm install
cp .env.example .env.local # set MCP_OAUTH_SIGNING_KEY for sign-in and/or MCP_API_KEY for operator access
npm run dev # http://localhost:3000/api/mcpEnvironment variables
Variable | Required | Purpose |
| for operator access | Operator key ( |
| for sign-in | 32+ random bytes; seals every OAuth artifact. Rotating it invalidates all issued tokens. |
| production | Public origin of this server (the OAuth issuer), e.g. |
| no | Canonical path of the MCP endpoint, appended to |
| recommended | The backend's |
| for any non-loopback client | Comma-separated redirect targets allowed to register: a host ( |
| no |
|
| off-Vercel only |
|
| no | Backend base. Unset, it defaults to the staging backend ( |
| recommended | Backend |
| no | Two budgets per principal per minute (SPLIT-1449), requests / tool calls: |
| no |
|
| recommended in prod | Shared store for the distributed rate limit, the sign-in throttle and the code replay cache. Vercel KV names |
Checks
npm run lint # eslint
npm run typecheck # tsc --noEmit
npm test # jest (unit + route + full OAuth flow against a mocked backend)
npm run build # next build
npm run verify # all of the above
npm run gen:docs # regenerate docs/mcp-tools.md + manifest.json from the tool registry
npm run gen:api # regenerate backend API types from openapi/openapi.jsonCI (.github/workflows/ci.yml) runs the same on every push and pull request. Vercel's Git integration deploys main.
Distributed rate limiting (Upstash)
Create a Redis database at console.upstash.com (the free tier is enough), open its REST API tab and copy the REST URL and token into UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN on the Vercel project. The Upstash integration from the Vercel Marketplace, which injects KV_REST_API_URL / KV_REST_API_TOKEN, works too. No npm dependency: the server talks to the REST API directly, one round trip per request, capped at 1.5 s. Keys are namespaced mcp: and never logged.
Social sign-in
The backend must list this server's callback in SOCIAL_AUTH_RETURN_ORIGINS (see the backend's .env.example; use the full path https://<this host>/oauth/social/callback so the backend only ever returns to that route, not to an arbitrary page on this origin) and have Google or Apple configured; the buttons appear automatically when GET /api/v1/auth/providers reports a provider.
Endpoints
Path | Purpose |
| MCP Streamable HTTP (stateless, JSON responses). Both always answer, on the same handler; only the canonical one ( |
| RFC 9728 protected-resource metadata. Answers for either path suffix; the document always names the canonical |
| RFC 8414 authorization-server metadata |
| RFC 7591 dynamic client registration (public clients) |
| Hosted Splitt sign-in (authorization code + PKCE; optional |
| Start Google/Apple sign-in from the hosted page (same-origin only) |
| Return leg: exchange code, Splitt session, authorization code for the client |
|
|
| RFC 7009 revocation |
The server's own HTTP contract is described in docs/openapi.json; the backend contract it consumes is snapshotted in openapi/openapi.json.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Travel tools for AI agents: plan and edit real trips, search stays and tours, import travel videos.
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
Multilingual travel guides, gear picks and booking links for AI travel agents.
Directory of APIs, merchants, and tools AI agents can actually use.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables AI agents to interact with the Strava API to retrieve athlete statistics and activity data. It provides tools for listing recent activities and fetching detailed information for specific workout sessions.7-
- AlicenseAqualityAmaintenanceEnables AI assistants to search and browse mountaineers.org for activities, courses, trip reports, and routes, and optionally access authenticated user data such as upcoming activities, badges, and member profiles.28176 npm2MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI clients to search and browse camping availability across Alberta Parks, BC Parks, and Parks Canada, including front-country and backcountry campgrounds, through a unified set of tools.-
- AlicenseAqualityDmaintenanceEnables AI agents to query and manage campground reservations, sites, and rate plans via the Campspot Online Booking API.8MIT