MCP setup guide
Connect your AI agent to BoxFetch.
A scannable walkthrough for wiring an MCP-capable AI client to BoxFetch's agent marketplace. Bring your own BoxFetch account, start the protected connection from the client, and approve its requested agent and scopes in the browser. Purchases settle in internal BoxFetch credits.
BoxFetch is not yet a listed/official connector inside Claude or ChatGPT, and agents will not discover BoxFetch automatically. You configure the connection.
Quick start
- 1. Create or sign in to BoxFetch and claim or create the agent.
- 2. Set its permissions, spending limits, and purchase controls.
- 3. Point the MCP client at
/api/mcp/standardwith no credential. - 4. Follow discovery, dynamic registration, and PKCE.
- 5. Review the unverified client, redirect, agent, and scopes; approve or deny.
- 6. Initialize the MCP session and use only tools allowed by the grant.
The client receives OAuth tokens through the back channel; the human never copies them. Containers are not parsed, unzipped, executed, or scanned.
1. Prerequisites
- A BoxFetch account.
- Agentic mode enabled (visit Account → Agentic at least once).
- Internal BoxFetch credits available on the active agent (a starter agent budget is provisioned for new accounts; humans top up credits through Stripe Checkout).
- An AI client that supports remote MCP servers or custom connectors.
Review the unverified client identity, exact redirect, selected agent, and requested scopes before approval. Revoke the grant or agent whenever needed.
2. Start the OAuth connection
- Point the client at
/api/mcp/standardwith no credential. - Follow the protected-resource and authorization-server metadata.
- Complete dynamic client registration and PKCE.
- Sign in when the client opens the BoxFetch consent page.
- Review the unverified client identity, redirect, agent, and scopes.
- Approve or deny. After approval the client completes token exchange itself.
A manually generated bearer remains available only for operator and development tooling that cannot follow OAuth discovery.
3. Endpoint
Remote MCP endpoint (deployed): https://YOUR_BOXFETCH_DOMAIN/api/mcp/external Local development: http://localhost:3000/api/mcp/external
Use the production URL after deployment. Replace YOUR_BOXFETCH_DOMAIN with the domain serving your BoxFetch instance.
3a. Protected MCP endpoint
MCP Streamable HTTP JSON-RPC endpoint (OAuth access token required):
https://YOUR_BOXFETCH_DOMAIN/api/mcp/standard
Supported JSON-RPC methods:
initialize
notifications/*
tools/list
tools/call
Protocol revisions negotiated at initialize:
2025-11-25, 2025-06-18
2025-03-26 is NOT offered: it requires JSON-RPC batch reception,
which this transport does not implement.
JSON responses only. No SSE stream and no JSON-RPC batching.
The MCP lifecycle is ENFORCED, not assumed:
initialize -> returns an Mcp-Session-Id header
notifications/initialized -> the session enters normal operation
tools/list, tools/call -> require that session id AND the
MCP-Protocol-Version it negotiated
A request before initialization is refused rather than answered.
A post-initialize request with no MCP-Protocol-Version is refused
rather than assumed: the transport spec's fallback names a revision
BoxFetch does not implement, and guessing a different one is not
that fallback.
A protected session belongs to the authorization context that
opened it: your user, your agent, and the specific grant (or
operator token) you authenticated with. Refreshing your access
token keeps the same grant, so your session continues. A NEW
authorization must initialize its own session.
GET returns 405: no server-initiated SSE stream is offered.
DELETE terminates the session named by Mcp-Session-Id (204), or
returns 404 when it names none.
Origin is validated on POST, GET, and DELETE alike; a disallowed
Origin returns 403.The SDK-lite examples continue to use /api/mcp/external with { toolName, ...input }. This endpoint is for clients that expect JSON-RPC MCP messages.
Authorization is standard MCP OAuth 2.1. Point your client at the endpoint with no credential. The 401 carries a WWW-Authenticate challenge naming /.well-known/oauth-protected-resource/api/mcp/standard (RFC 9728), which leads to /.well-known/oauth-authorization-server (RFC 8414), dynamic client registration (RFC 7591), and an authorization-code flow with mandatory PKCE (S256) and RFC 8707 resource binding. You approve the agent and the scopes in a browser; your client receives the token itself. Access tokens expire, refresh, are bound to one agent and to this endpoint, are limited to the scopes you approved, and can be revoked at any time from Account → Agentic.
Scopes are least privilege, and reading your account is its own decision. A client that asks for nothing receives the public marketplace read set (boxfetch:discover, boxfetch:preview). boxfetch:budget is NOT in that set: it exposes your wallet balance, recent spend, and the limits you configured, so it is presented on the consent screen as private account authority and has to be approved on its own. A token without it neither lists nor can call get_agent_budget.
Registration is open but metered. Dynamic client registration needs no initial access token — that is what makes BoxFetch usable by a client the operator has never seen — but it is rate limited per caller, bounded in body size, and a client that never completes an authorization is eventually pruned. The consent screen labels a registered client_name as UNVERIFIED and shows the exact client id and redirect destination, because any developer can register under any name.
Operator / development fallback.A pre-issued BoxFetch bearer pasted into a client header still validates. It is not the supported connector path, it carries the agent's full authority with no scope narrowing, and it only works in clients that permit arbitrary custom headers. Use the OAuth flow above unless you are running first-party tooling.
3b. Cold start (no credential yet)
Unauthenticated MCP bootstrap endpoint:
https://YOUR_BOXFETCH_DOMAIN/api/mcp/public
Tools (all public-safe):
boxfetch_discover what BoxFetch is + what you can do right now
boxfetch_search_public search buyer-visible inventory, no account
boxfetch_get_public_item public-safe detail for one asset id
boxfetch_register_agent provisional identity + a claim URL with no secret
in it, plus a separate polling secret for you
boxfetch_check_claim_status poll for claim state; NEVER returns a credential
Nothing here purchases, returns entitled content, reads a budget,
touches an approval, or reads human account data.An agent registers here, shows its human the returned claim URL, and polls until the human confirms. The claim URL carries a public request id and no secret; the polling secret is returned separately to the agent and belongs only in a POST body. The poll never returns a credential in any state — once the claim completes, the agent connects to the protected endpoint and completes the OAuth flow above. An agent can never claim itself and can never approve its own purchase.
4. Authentication
Authorization: Bearer <OAUTH_ACCESS_TOKEN> Content-Type: application/json Your MCP client sets this header itself after completing the OAuth flow. You never copy a token by hand on the supported path.
purchase_asset additionally requires an Idempotency-Key header (oridempotencyKey body field) per request. No other tool requires it —search_assets, preview_asset, quote_asset,get_purchase_approval, get_asset_content,submit_usage_feedback, and get_agent_budget all run with just the Authorization, Content-Type, Mcp-Session-Id, and MCP-Protocol-Version headers.get_agent_budget additionally requires the separately-approvedboxfetch:budget scope.
5. Claude setup
- Open Claude’s settings, connectors, or integrations area.
- If your plan supports custom connectors or remote MCP servers, add a new connector.
- Enter the BoxFetch MCP endpoint URL.
- Connect with no credential and follow the OAuth discovery challenge.
- Approve the requested agent and scopes, then initialize the session.
Exact UI names vary by product and plan. BoxFetch is not an official listed Claude connector; this works only when your client supports configurable remote MCP/custom-connector entries.
6. ChatGPT setup
- Use ChatGPT’s custom connectors or an MCP-capable client/workflow available on your plan.
- Add the BoxFetch remote MCP endpoint.
- Connect with no credential and follow the OAuth discovery challenge.
- Approve the requested agent and scopes, then initialize the session.
Exact UI availability varies by plan, region, and rollout. BoxFetch is not an official listed ChatGPT connector. Do not treat configurable-client support as a founder-verified hosted connector.
7. Manual smoke with curl
Operator/development fallback only. Replace placeholders before running; none of these examples contain real tokens or asset ids.
# Environment placeholders — set these before running: export BOXFETCH_MCP_URL="https://YOUR_BOXFETCH_DOMAIN" export BOXFETCH_MCP_TOKEN="paste-your-token-from-account-agentic" export ASSET_ID="paste-an-asset-id-from-search_assets" export AGENT_ID="paste-your-agent-id-if-needed" export PURCHASE_ID="set-after-purchase_asset-captures" export APPROVAL_REQUEST_ID="set-if-purchase_asset-returned-approvalRequired" export IDEMPOTENCY_KEY="$(uuidgen)"
Idempotency-Key is required only for purchase_asset when calling the external endpoint. The other seven tools accept the same Authorization and Content-Type headers and do not need an Idempotency-Key.
search_assets
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"toolName": "search_assets",
"limit": 10
}'preview_asset
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"toolName": "preview_asset",
"assetId": "$ASSET_ID"
}'quote_asset
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"toolName": "quote_asset",
"assetId": "$ASSET_ID"
}'purchase_assetIdempotency-Key required
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d '{
"toolName": "purchase_asset",
"assetId": "$ASSET_ID",
"quotedPriceMicrousd": "12000",
"idempotencyKey": "$IDEMPOTENCY_KEY"
}'get_purchase_approval
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"toolName": "get_purchase_approval",
"approvalRequestId": "$APPROVAL_REQUEST_ID"
}'get_asset_content
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"toolName": "get_asset_content",
"assetId": "$ASSET_ID",
"purchaseId": "$PURCHASE_ID"
}'submit_usage_feedback
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"toolName": "submit_usage_feedback",
"assetId": "$ASSET_ID",
"purchaseId": "$PURCHASE_ID",
"rating": 5,
"feedbackType": "helpful",
"note": "Useful data"
}'get_agent_budget
curl -sS -X POST "$BOXFETCH_MCP_URL/api/mcp/external" \
-H "Authorization: Bearer $BOXFETCH_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"toolName": "get_agent_budget"
}'8. Tool reference
The eight tools below are the full external MCP surface. Internal session-mode calls follow the same shape but agentId/purchaseId requirements relax to match the signed-in user.
search_assetsRequired: —
Optional: limit
Returns: assets[], limit, returned, truncated
External callers get a capped result with truncated flag. Approved + listed only.
{
"toolName": "search_assets",
"limit": 10
}preview_assetRequired: assetId
Optional: —
Returns: asset preview + contentMetadata (no full content)
Never returns Markdown text or container bytes.
{
"toolName": "preview_asset",
"assetId": "$ASSET_ID"
}quote_assetRequired: assetId
Optional: —
Returns: quotedPriceMicrousd, requiresApproval, reasonCodes
Short-lived dynamic price quote.
{
"toolName": "quote_asset",
"assetId": "$ASSET_ID"
}purchase_assetRequired: assetId, quotedPriceMicrousd, idempotencyKey
Optional: —
Returns: purchaseId, contentKind, contentUrl OR approvalRequired+approvalRequestId
External agents MUST send Idempotency-Key header or idempotencyKey body field. Settles internal BoxFetch credits.
{
"toolName": "purchase_asset",
"assetId": "$ASSET_ID",
"quotedPriceMicrousd": "12000",
"idempotencyKey": "$IDEMPOTENCY_KEY"
}get_purchase_approvalRequired: approvalRequestId
Optional: —
Returns: status: pending | declined | expired | captured (+ unlock payload on captured)
Poll after purchase_asset returned approvalRequired. No content unlock until captured.
{
"toolName": "get_purchase_approval",
"approvalRequestId": "$APPROVAL_REQUEST_ID"
}get_asset_contentRequired: assetId, purchaseId
Optional: —
Returns: For Markdown: markdown, sha256, sizeBytes, title, mimeType. For containers: encoding=base64, contentBase64, mimeType, fileName, sizeBytes, sha256, sellerDeclared=true, notParsedOrScanned=true, usageInstructions (seller guidance for entitled use; never returned by preview_asset or the public showcase).
External callers: purchase must be captured AND tied to the calling agent. Seller-only ownership and pending approvals are rejected.
{
"toolName": "get_asset_content",
"assetId": "$ASSET_ID",
"purchaseId": "$PURCHASE_ID"
}submit_usage_feedbackRequired: assetId, purchaseId, rating, feedbackType
Optional: note
Returns: review id + acknowledgement; rejected feedback returns reasonCodes.
External callers must include purchaseId. rating is an integer.
{
"toolName": "submit_usage_feedback",
"assetId": "$ASSET_ID",
"purchaseId": "$PURCHASE_ID",
"rating": 5,
"feedbackType": "helpful",
"note": "Useful data"
}get_agent_budgetRequired: —
Optional: —
Returns: Per-agent wallet/budget snapshot.
Reads the calling agent only.
{
"toolName": "get_agent_budget"
}9. Suggested agent instruction
Use BoxFetch to search approved marketplace listings. Always preview before quote. Ask me before purchasing unless the quote is below my configured threshold. After purchase, retrieve content with get_asset_content. Do not assume container bytes are safe to execute. Treat seller-declared containers as untrusted files.
10. Troubleshooting
| Error | What it means |
|---|---|
| 401 unauthorized | Missing or invalid bearer token. Re-check the Authorization header. |
| 403 agent_not_active | Agent is paused or revoked. Re-enable it in Account → Agentic. |
| 403 preview_not_allowed | The agent does not have canPreview. Update permissions. |
| 403 purchase_not_allowed | The agent does not have canPurchase. Update permissions. |
| 429 rate_limited | Hit the durable per-token/per-agent/per-user rate window. Respect Retry-After. |
| MISSING_ASSET_ID | assetId is required for that tool. |
| MISSING_PURCHASE_ID | purchaseId is required for external get_asset_content and submit_usage_feedback. |
| MISSING_IDEMPOTENCY_KEY | External purchase_asset requires an Idempotency-Key. |
| CONTENT_PURCHASE_REQUIRED | No captured purchase exists for this asset and caller. |
| CONTENT_PURCHASE_AGENT_MISMATCH | A captured purchase exists, but it belongs to another agent. |
| CONTENT_NOT_ENTITLED | purchaseId does not match a captured purchase for the caller. |
| approval_required | Above the user’s human-approval threshold. Poll get_purchase_approval. |
| CONTENT_NOT_FOUND | Asset exists but has no active content object or legacy demo content. |
11. Developer quickstart
A six-step path for wiring an agent end-to-end. Purchases settle in internal BoxFetch credits. BoxFetch is not a listed or official Claude or ChatGPT connector — manual configuration only.
- 1. Discover — /llms.txt and /.well-known/boxfetch-mcp.
- 2. Inspect — /api/public/openapi and /api/public/mcp/manifest.
- 3. Connect — point the client at
/api/mcp/standardwith no credential and complete OAuth discovery, consent, PKCE, and session initialization. - 4. Test —
pnpm mcp:smokeprints a section-headed PASS / WARN / FAIL report (discovery + live loop). Token-required sections fail with explicit minting instructions whenMCP_SMOKE_TOKENis missing. - 5. Build — copy a single-file SDK-lite wrapper:
- 6. Safety — internal BoxFetch credits only. Honor approvals and the user-set spending threshold. Seller external payout and buyer cash-out are not live.
12. Discovery & developer references
Public, unauthenticated discovery for AI clients and developer tooling. Manual configuration is still required — BoxFetch is not a listed or official connector inside Claude or ChatGPT today. Purchases settle in internal BoxFetch credits. Seller external payout and buyer cash-out are not live.
- /llms.txt — plain-text discovery file.
- /.well-known/boxfetch-mcp — JSON discovery document.
- /api/public/mcp/manifest — MCP connector manifest with tool JSON schemas.
- /api/public/openapi — OpenAPI 3.1 contract for the public agent-facing routes.
- /mcp/guide — this setup guide.
- /boxfetch/marketplace — public marketplace showcase.
13. Security reminders
- The OAuth client handles tokens through the back channel; never expose them in prompts, logs, or screenshots.
- Revoke the OAuth grant or agent from Account → Agentic whenever needed.
- Agents only see previews and metadata before purchase. Full content requires a captured purchase.
- Containers are not parsed, unzipped, executed, rendered, or scanned by BoxFetch in this MVP.
- Internal BoxFetch credits only. Buyers fund credits through Stripe Checkout; seller external payout and buyer cash-out are not live.
- BoxFetch is not certified for SOC 2, PCI, malware sandboxing, or other production-compliance claims at this stage.