PearPear
MCP ServerOrchard MCP

Pear MCP integration guide

Build a Pear MCP integration with authentication, volume attribution, account selection, and trading tools.

Use this guide to build an MCP client or a server-side integration for Pear. If you only want to connect an existing MCP client, read the Orchard MCP user guide.

Integration flow

A complete trading flow has eight steps:

  1. Connect to the Pear MCP endpoint.
  2. Authenticate the user with OAuth 2.0 or an API key.
  3. Call list_trade_accounts and select a trade account.
  4. Call sync_account before you read positions.
  5. Call read tools to find assets and review account data.
  6. Call a plan_* tool and show the plan to the user.
  7. After user approval, call the matching execute_* tool.
  8. Sync the account and check the execution result.

A read-only integration uses steps 1 through 5. It does not need the write scope.

Choose an authentication method

Pear supports two authentication methods.

MethodUse it forCredential
OAuth 2.0A client where a user signs in and approves accessBearer access token
API keyA trusted server-side integrationx-api-key header

Use OAuth 2.0 for a user-facing client. Do not put an API key in browser code.

Authentication does not connect an exchange account. Users connect and manage trade accounts in the Pear application. Never ask a user to send exchange credentials through an MCP tool.

Service contract

ItemValue
MCP endpointhttps://mcp.pearprotocol.io/mcp
TransportStreamable HTTP with JSON responses
Health endpointGET https://mcp.pearprotocol.io/health
Protected-resource metadataGET https://mcp.pearprotocol.io/.well-known/oauth-protected-resource/mcp
OAuth authorization serverhttps://pro-gateway.pearprotocol.io
AuthenticationOAuth 2.0 bearer token or x-api-key
Read scopemcp:read
Write scopemcp:write
Request limit100 MCP HTTP requests per authenticated user in 60 seconds

Connect and authenticate

OAuth 2.0 flow

The Pear authorization server uses the authorization code flow with PKCE S256. It supports dynamic client registration and refresh tokens. The client is public. Set token_endpoint_auth_method to none.

Use this flow:

  1. Send an unauthenticated request to the MCP endpoint.
  2. Read the WWW-Authenticate response header.
  3. Get the RFC 9728 metadata URL from resource_metadata.
  4. Get the protected-resource metadata from that URL.
  5. Get the authorization server URL from authorization_servers[0].
  6. Get the authorization server metadata.
  7. Register the application at the listed registration_endpoint when you do not have a client registration.
  8. Redirect the user to the listed authorization_endpoint.
  9. Send an authorization code request with PKCE S256.
  10. Let the Pear page handle sign-in and consent.
  11. Exchange the authorization code at the listed token_endpoint.
  12. Send the access token in the Authorization: Bearer <access-token> header.
  13. Use the refresh token when the access token expires.

Store state and the PKCE verifier in one short-lived authorization transaction. Compare the returned state with the stored value. Stop the flow when the values do not match.

Request only the scopes that the application needs.

ScopeAccess
mcp:read13 read tools and the pear://asset-filters resource
mcp:write16 write tools, including all plan_* tools
mcp:read mcp:writeAll tools and resources

Register an OAuth client

Send this request to the registration endpoint:

POST <registration_endpoint>
Content-Type: application/json

{
  "redirect_uris": ["https://client.example.com/oauth/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "client_name": "Example MCP Client"
}

The redirect URI must use HTTPS. Pear also accepts an HTTP redirect URI for localhost, 127.0.0.1, or ::1.

Request an authorization code

Send these parameters to the authorization endpoint:

response_type=code
client_id=<oauth-client-id>
redirect_uri=<registered-redirect-uri>
scope=mcp:read mcp:write
state=<random-state>
code_challenge=<base64url-sha256-verifier>
code_challenge_method=S256

Exchange the authorization code

Send the returned code as form data:

POST <token_endpoint>
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&client_id=<oauth-client-id>&redirect_uri=<registered-redirect-uri>&code=<authorization-code>&code_verifier=<pkce-verifier>

The OAuth client_id identifies the OAuth application. It does not identify the integration for volume attribution.

API key flow

Send the API key in the x-api-key header on each MCP request.

API keys have these scopes:

API key scopeMCP scopesAccess
readmcp:readRead tools only
read_writemcp:read, mcp:writeAll tools

You cannot create or revoke an API key through MCP. A signed-in user can create a key in the Pear application. The user can also call POST /api-keys on the Pear gateway.

POST https://pro-gateway.pearprotocol.io/api-keys
Authorization: Bearer <first-party-session-token>
Content-Type: application/json

{
  "label": "Example MCP integration",
  "scope": "read_write",
  "expiresAt": "2027-01-01T00:00:00Z"
}

expiresAt is optional. The response returns the raw key one time. Store the key in a secret manager.

Use GET /api-keys to list keys. Use DELETE /api-keys/:id to revoke a key.

The MCP validates a key through GET /auth/api-key/me. An unknown, expired, or revoked key gets HTTP 401.

An API key has priority when a request has both credential headers. An invalid API key does not fall back to the bearer token.

Send an MCP request

Use an MCP SDK in production. This raw request shows API-key authentication and optional volume attribution:

curl https://mcp.pearprotocol.io/mcp \
  --request POST \
  --header 'content-type: application/json' \
  --header 'accept: application/json, text/event-stream' \
  --header 'x-api-key: <api-key>' \
  --header 'x-client-id: <client-code>' \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {}
  }'

For OAuth, replace x-api-key with Authorization: Bearer <access-token>.

Add volume attribution

Add a Pear-issued code to each MCP request that needs volume attribution:

x-api-key: <api-key>
x-client-id: <client-code>

The value must be an active client_ids.code that Pear assigned. The value is not any of these identifiers:

  • OAuth client_id
  • API key UUID
  • Raw API key
  • User UUID
  • Trade account UUID

Pear records the code on supported executions and fills. Pear can then group trading volume by integration.

x-client-id is an attribution label. It is not an authentication credential. Pear checks that the code exists and is active. Pear does not bind the code to an API key or OAuth client.

Send x-client-id on every request that needs attribution. The value does not continue to the next request.

When you omit x-client-id, the trade has no integration attribution unless the service has a default code. An unknown or inactive code causes the related write to fail.

Attribution covers market trades, TWAP schedules, conditional triggers, and manual rebalances. Ladder creation and automatic rebalance settings do not automatically receive the default attribution code.

These fields have separate purposes:

FieldPurpose
x-api-key or bearer tokenIdentifies and authorizes the user
x-client-idIdentifies the integration for volume attribution
tradeAccountIdSelects the connected exchange account

Build the account flow

A trade account is a connected exchange account. It tells Pear which exchange, wallet, or subaccount a tool must use.

Users manage trade accounts in the Pear application. MCP does not create, change, delete, restore, or return credentials for a trade account.

Select an account

Call list_trade_accounts when the client does not have a current account. This tool does not need a tradeAccountId.

Use this selection flow:

  1. Call list_trade_accounts.
  2. If the list is empty, tell the user to connect an account in Pear.
  3. If the list has one active account, omit tradeAccountId. MCP selects that account.
  4. If the list has multiple active accounts, show an account picker.
  5. Pass the selected account id as tradeAccountId.
  6. Keep the selection for the current task.
  7. Pass the same ID to later account-scoped calls.

Use the same tradeAccountId for both parts of a plan_* and execute_* flow. A plan token belongs to one user and one trade account.

Use Alias, Connector as the account label. For example, use Main, Hyperliquid. Show a short exchangeIdentifier only when two accounts have the same label.

The tool can return these account errors:

ConditionClient action
No accountAsk the user to connect an account in Pear.
Multiple accounts with no selectionShow the returned account list and ask the user to select one.
Unknown account or another user's accountRefresh the account list and ask the user to select again.

Do not show the raw error as the only response. Tell the user what action to take.

All order tools are account-scoped. Position, balance, execution, TCA, pending-order, rebalance, saved-basket, cancellation, management, and synchronization tools are also account-scoped.

Market discovery, basket discovery, prediction-market search, notifications, and list_trade_accounts do not need an account selection.

Account fields

Each account from list_trade_accounts has these fields:

FieldClient use
idPass this stable ID to account-scoped tools. You do not have to show it in the label.
aliasUse this user-defined name as the main label.
connectorShow the connected exchange, such as Hyperliquid, Binance, Bybit, OKX, or Lighter.
exchangeIdentifierShow a short form when this value is an address.
metadataShow only details that help the user identify the account.
createdAt, updatedAtDo not show these values in a normal account picker.
deletedAtThis field exists only for a deleted account.

list_trade_accounts accepts includeDeleted. Keep this value false during normal use. An account-scoped tool cannot use a deleted account.

Sync the account

Call sync_account after the user connects an account. Call it before the first position read. Call it again after an order settles.

The tool imports exchange positions and fills into Pear. It does not place an order.

Build the trade flow

Every action that places an order uses a plan tool and an execute tool.

  1. Call the matching plan_* tool.
  2. Keep the returned single-use planToken.
  3. Show the complete plan to the user.
  4. Wait for user approval.
  5. Call the matching execute_* tool.
  6. Send the token and the required routing field.
  7. Check the execution result.
  8. Call sync_account after the order settles.

A plan validates and sizes the action. It does not place an order.

An execute_* tool does not accept the original planning fields. It uses the stored plan. The token belongs to one user, trade account, tool family, and routing mode.

Handle an unclear execution result

Do not create a new plan after an unclear execution result. First call these tools:

  1. Call sync_account.
  2. Call get_position.
  3. Call get_execution when you have an execution ID.

Use this recovery flow for binding_mismatch, execution_in_progress, and unknown or expired token responses. These responses do not prove that Pear did not place an order.

Handle schemas and responses

Use MCP tools/list as the source for each input schema. The server validates arguments before it calls the execution engine.

Interactive hosts can show widgets for markets, positions, orders, baskets, notifications, plans, and execution receipts. Other hosts receive structured JSON or JSON text.

The server rejects a plain JSON-text response above an estimated 25,000 tokens. This limit does not apply to widget-backed structured responses. Use filters, limit, cursor, or offset to request less data.

Tool reference

The current manifest contains 29 tools. It has 13 read tools and 16 write tools.

Read tools

These tools require mcp:read.

ToolAccountPurpose
discover_assetsNoSearches the asset catalog across connectors. It supports filters, sorting, cursor paging, and compact or full output. Read pear://asset-filters before you use connector, asset-class, or category filters.
get_account_summaryYesReturns exchange balances when params.scope is balance. Returns Pear performance statistics when params.scope is stats.
get_executionYesReturns one execution by executionId. Use it to check execution and order errors after a write.
get_positionYesReturns all open Pear positions with profit and loss, funding, leverage, triggers, current executions, and stale-data signals.
get_position_historyYesReturns recent closed positions. The default limit is 10.
get_tcaYesReturns transaction-cost analysis for execution, position, or summary. Execution and position requests need the related ID.
list_auto_rebalanceYesLists settings when params.scope is configs. Lists position drift checks when params.scope is events.
list_basketsNoLists live pair and basket markets for a connector. It supports scope, symbol search, limit, and offset.
list_notificationsNoLists all, read, or unread notifications. It supports optional ISO 8601 start and end dates.
list_pending_ordersYesLists schedules, triggers, or ladders. A ladder request can include ladderId to return its settings and rung triggers.
list_saved_basketsYesLists saved basket templates with current price, change, and funding data.
list_trade_accountsNoLists connected trade accounts. It never returns exchange credentials.
search_prediction_marketsNoSearches open Kalshi or Polymarket markets. plan_open_basket can use the returned market IDs in a prediction-market condition.

Order plan and execute tools

These tools require mcp:write.

ToolPurpose
plan_open_basketPlans a basket open with a market, TWAP, trigger, or ladder order. It returns a plan and planToken.
execute_open_basketPlaces the approved open plan. Send the same executionStyle, the planToken, and tradeAccountId when needed. A market order can also use expectedTotalNotionalUsd as a check.
plan_close_basketPlans a market or TWAP close. A market close can target one position, selected symbols, or all positions. A TWAP close targets one position.
execute_close_basketPlaces the approved close plan. Send the same executionStyle and planToken.
plan_set_position_tpslPlans one take-profit, stop-loss, or trailing close trigger. Plan take-profit and stop-loss triggers separately.
execute_set_position_tpslStarts the exact trigger in the approved plan.
plan_rebalance_positionPlans new target weights for an open basket. It shows the current weights, target weights, and estimated USD changes.
execute_rebalance_positionPlaces the approved rebalance. The engine calculates trade changes from current prices.
plan_adjust_positionPlans an increase or decrease for one leg or all legs. It supports percent or USD size. A decrease cannot reverse a leg.
execute_adjust_positionPlaces the approved adjustment. The engine calculates quantity from the current price for a USD size.
plan_enable_auto_rebalancePlans an automatic rebalance setting. params.weightSource is live_beta or initial_weight. live_beta also uses a 1h, 4h, or 1d time frame.
execute_enable_auto_rebalanceStarts the approved automatic rebalance setting. Send the same weightSource and planToken.

Other write tools

These tools require mcp:write.

ToolAccountPurpose
cancel_pending_orderYesCancels one or all TWAP schedules, one or all triggers, or one ladder and its active rungs. It does not use a plan token.
manage_saved_basketYesSaves, changes, or deletes basket templates. It does not use a plan token.
set_notification_read_stateNoMarks one notification as read or unread. It can also mark all notifications before a time as read.
sync_accountYesMatches Pear positions and fills with exchange data. It does not place an order or use a plan token.

MCP resources

The mcp:read scope exposes pear://asset-filters. This resource returns the connectors, asset classes, and categories that discover_assets accepts.

MCP Apps hosts can also read hash-pinned ui:// resources for the registered widgets. These resources show tool results. They do not change authentication or tool behavior.

Errors and security

ConditionResult
Missing or invalid credentialsHTTP 401 with an RFC 9728 challenge
Too many requestsHTTP 429 with Retry-After
Read-only credential calls a write toolMCP protocol error because the tool is not registered
Both credential headers are presentThe API key has priority
Plan token is reused or expiredThe write fails or returns the stored replay result

The MCP validates bearer JWTs locally. It does not check OAuth grant revocation on every request. The Pear gateway checks revocation for engine-backed calls. A revoked token can reach cache-only reads until the JWT expires.

API keys never appear in tool arguments or tool results. MCP does not expose exchange credentials or trade-account changes as tools.

Plan tokens are single-use and expire. Redis stores token state and the replay result.

Each MCP request receives only the tools that its verified scopes allow.

Integration checklist

Before release, verify these items:

  • Use OAuth 2.0 with PKCE S256 for a user-facing client.
  • Use a read_write API key only when the integration needs write tools.
  • Keep API keys out of source control and browser storage.
  • Send x-client-id on each request that needs volume attribution.
  • Confirm that Pear activated the client_ids.code.
  • Call list_trade_accounts before the first account-scoped tool.
  • Call sync_account before position reads and after settled executions.
  • Show each plan_* result before you call the matching execute_* tool.
  • Page large read results.
  • Handle HTTP 401, HTTP 429, tool errors, and unclear execution results.

On this page