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. 1. Create or sign in to BoxFetch and claim or create the agent.
  2. 2. Set its permissions, spending limits, and purchase controls.
  3. 3. Point the MCP client at /api/mcp/standard with no credential.
  4. 4. Follow discovery, dynamic registration, and PKCE.
  5. 5. Review the unverified client, redirect, agent, and scopes; approve or deny.
  6. 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

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

  1. Point the client at /api/mcp/standard with no credential.
  2. Follow the protected-resource and authorization-server metadata.
  3. Complete dynamic client registration and PKCE.
  4. Sign in when the client opens the BoxFetch consent page.
  5. Review the unverified client identity, redirect, agent, and scopes.
  6. 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

  1. Open Claude’s settings, connectors, or integrations area.
  2. If your plan supports custom connectors or remote MCP servers, add a new connector.
  3. Enter the BoxFetch MCP endpoint URL.
  4. Connect with no credential and follow the OAuth discovery challenge.
  5. 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

  1. Use ChatGPT’s custom connectors or an MCP-capable client/workflow available on your plan.
  2. Add the BoxFetch remote MCP endpoint.
  3. Connect with no credential and follow the OAuth discovery challenge.
  4. 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_assets

Required:

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_asset

Required: assetId

Optional:

Returns: asset preview + contentMetadata (no full content)

Never returns Markdown text or container bytes.

{
  "toolName": "preview_asset",
  "assetId": "$ASSET_ID"
}
quote_asset

Required: assetId

Optional:

Returns: quotedPriceMicrousd, requiresApproval, reasonCodes

Short-lived dynamic price quote.

{
  "toolName": "quote_asset",
  "assetId": "$ASSET_ID"
}
purchase_asset

Required: 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_approval

Required: 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_content

Required: 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_feedback

Required: 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_budget

Required:

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

ErrorWhat it means
401 unauthorizedMissing or invalid bearer token. Re-check the Authorization header.
403 agent_not_activeAgent is paused or revoked. Re-enable it in Account → Agentic.
403 preview_not_allowedThe agent does not have canPreview. Update permissions.
403 purchase_not_allowedThe agent does not have canPurchase. Update permissions.
429 rate_limitedHit the durable per-token/per-agent/per-user rate window. Respect Retry-After.
MISSING_ASSET_IDassetId is required for that tool.
MISSING_PURCHASE_IDpurchaseId is required for external get_asset_content and submit_usage_feedback.
MISSING_IDEMPOTENCY_KEYExternal purchase_asset requires an Idempotency-Key.
CONTENT_PURCHASE_REQUIREDNo captured purchase exists for this asset and caller.
CONTENT_PURCHASE_AGENT_MISMATCHA captured purchase exists, but it belongs to another agent.
CONTENT_NOT_ENTITLEDpurchaseId does not match a captured purchase for the caller.
approval_requiredAbove the user’s human-approval threshold. Poll get_purchase_approval.
CONTENT_NOT_FOUNDAsset 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. 1. Discover /llms.txt and /.well-known/boxfetch-mcp.
  2. 2. Inspect /api/public/openapi and /api/public/mcp/manifest.
  3. 3. Connect — point the client at /api/mcp/standard with no credential and complete OAuth discovery, consent, PKCE, and session initialization.
  4. 4. Testpnpm mcp:smoke prints a section-headed PASS / WARN / FAIL report (discovery + live loop). Token-required sections fail with explicit minting instructions when MCP_SMOKE_TOKEN is missing.
  5. 5. Build — copy a single-file SDK-lite wrapper:
    • TypeScript — examples/mcp/typescript/client.ts (docs)
    • Python — examples/mcp/python/client.py (docs)
  6. 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.

13. Security reminders