Model Context Protocol

Your Portfolio, Inside Your Own AI Assistant

A read-only MCP server over your own Artha account, so your assistant answers from your holdings instead of guessing at a screenshot.

Connector URL

https://arthaterminal.com/api/mcp

Four steps

Quick Start

Connecting is a settings step in your assistant, not something you can ask it to do. It takes about a minute, once. After that you ask in plain English.

  1. Copy the connector URL

    It is the field at the top of this page.

  2. Add it as a custom connector

    In Claude that is Settings → Connectors → Add custom connector. In ChatGPT it is Settings → Connectors. In Cursor it is Settings → MCP → Add server.

  3. Sign in and choose what it may read

    A window opens on arthaterminal.com. Sign in, then tick the permissions you want to grant.

  4. Ask it something

    For example: what is my largest holding, and when was it last synced?

Your Assistant, Step by Step

WhereSettings, then Connectors. Same steps on claude.ai in a browser.

  1. 1Open Settings and select Connectors.
  2. 2Scroll to the bottom of the list and select Add custom connector.
  3. 3Give it a name, Artha Terminal, and paste the connector URL below into the Remote MCP server URL field. Leave the advanced OAuth client fields empty, Artha registers the client for you.
  4. 4Select Connect. A browser window opens on Artha.
  5. 5Sign in if you are not already, then tick the scopes you want to grant and select Approve.
  6. 6Back in Claude, Artha appears in the connector list. Ask it something like: what is in my Artha watchlist?
Remote MCP server URL
https://arthaterminal.com/api/mcp

Free accounts can hold one custom connector. Paid plans can hold several.

Seventeen tools

What It Gives You

Five groups of read-only tools over your own account. A question that works in one connected client works in all of them, because every client calls the same tools.

Five things to ask

Claude Desktop and Claude Code both add a remote MCP server by URL. Once you approve the connector, ask in plain English.

  • What is my portfolio worth right now, and when was it last synced?
  • Break my holdings down by sector and tell me where I am most concentrated.
  • What is my Sharpe ratio, and is the sample large enough to quote it?
  • List the price alerts I have set that have not triggered yet.
  • What does my household hold in common, and how many members are counted in that figure?

The tools, by group

Portfolio

Totals, individual holdings, mutual funds, SIPs and fund orders, the breakdown by sector, market-cap band, or instrument type, and the stored fundamentals of the stocks you hold or watch. Every figure states when it was last synced, and the allocation states what share of the portfolio it could classify.

get_portfolio_overview, get_holdings, get_allocation, get_portfolio_history, list_broker_connections, get_mutual_fund_sips, get_mutual_fund_orders, get_fundamentals

Risk

Sharpe, Sortino, beta, R-squared, maximum drawdown, volatility, and value at risk, computed on Indian conventions: 252 trading days and a 6.5 percent risk-free rate. Every result reports the sample it rests on and flags a sample too small to quote.

get_risk_metrics

Watchlists

Your watchlists and the symbols on them, your price and portfolio alerts with the condition in a plain sentence, your saved screens with their conditions and match counts, and reference lookup across the NSE-listed universe.

list_watchlists, list_alerts, search_symbols, list_saved_screens

Family

Household totals and combined exposure by symbol and by sector, across the members who chose to allow it. Aggregates only. No tool can name a member or enumerate what they hold.

list_families, get_family_overview, get_family_exposure

Account

Who the connected account belongs to. The one tool that needs no scope at all, so a connection you approve without ticking anything still resolves your display name and when you joined.

get_profile

With no broker connected, every portfolio tool returns nothing

That is the designed behaviour, not a failure. Artha holds nothing for an account that has never synced, so each tool returns an empty result, a null date, and a sentence explaining why, which your assistant can relay word for word. Connect a broker and run a sync, or the answers stay correct and empty.

Connect a broker in settings

Permissions

Your Data and Permissions

You tick each permission separately when you connect. There are three, and granting one does not grant the others. A tool whose scope you did not grant is never offered to the assistant, so it cannot be called.

portfolio:read
Read your holdings, mutual funds and SIPs, fund orders, portfolio value, risk metrics, and the stored fundamentals of those stocks
watchlist:read
Read your watchlists, price alerts, and saved screens
family:read
Read your family's combined exposure, for members who allowed it

Read-only

Every tool reads. None writes. There is no path from the MCP server to your data, your settings, or your broker.

Scoped

You approve each scope separately on the consent screen. A tool whose scope you did not grant is not offered and cannot be called.

Revocable

Access is granted per client through OAuth and stays tied to your Artha account. Disconnect it and Artha stops answering that assistant, and the approval is withdrawn at the login provider too.

No orders

Artha is not a broker and no write path to one exists. An assistant connected here cannot place, change, or cancel a trade.

No credentials

Broker tokens and client ids never leave Artha. The connections tool returns the broker name, the connection status, and the last sync time, and nothing else.

Taking access back

Access is revoked from Settings → API Keys → Connected assistants, and stops on the next request. Every assistant you have connected is listed there, one row each.

Developer documentation

Tools

Seventeen tools, all read-only. Every result carries as_of, the date or timestamp of the underlying data rather than of the request, and is_demo, which is true for the seeded demo accounts. Any result holding a monetary value also carries currency: "INR". List results add truncated and total_available.

ToolScopeInputReturns
get_profileAny valid tokenNo inputuser_id, display_name, username, member_since
get_portfolio_overviewportfolio:readNo inputtotal_value, total_invested, total_pnl, total_pnl_percent, day_pnl, day_pnl_percent, holdings_count. Where funds are held, also breakdown (equity, and mutual_funds with nav_as_of) and day_pnl_covers
get_holdingsportfolio:readlimit (1 to 200, defaults to 50), sortBy (value, pnl, pnlPercent, symbol)symbol, name, exchange, quantity, average_cost, last_close, value, unrealised_pnl, unrealised_pnl_percent, weight_pct. Where funds are held, also mutual_funds with isin, fund_name, folio, units, average_cost, nav, nav_date, value, unrealised_pnl and unrealised_pnl_percent. A fund has no exchange and no last_close
get_allocationportfolio:readby (sector, marketCap or instrument), requiredby, slices with name, value and weight_pct, coverage_pct, holdings_count. Where funds are held, also mutual_funds with included, positions, value, nav_as_of and excluded_reason
get_portfolio_historyportfolio:readrange (1M, 3M, 6M, 1Y or MAX), requiredrange, points of recorded_at, value, invested and pnl
get_risk_metricsportfolio:readbenchmark (NIFTY50), optional and the only accepted valuesharpe, sortino, beta, r_squared, max_drawdown_pct, volatility_pct, value_at_risk_95, value_at_risk_99, conditional_var_95, beta_coverage_pct, observations, insufficient_sample, risk_free_rate, trading_days_per_year, holdings_measured, holdings_excluded, holdings_as_of
list_broker_connectionsportfolio:readNo inputbroker, status, is_active, connected_at, last_synced. No credentials of any kind.
get_mutual_fund_sipsportfolio:readlimit (1 to 200, defaults to 50), includeEnded (defaults to false), both optionalsummary with active_count, paused_count, ended_count, monthly_equivalent, next_instalment, due_next_30_days and settings_as_of; sips with sip_id, isin, fund_name, frequency, instalment_amount, next_instalment, status and ended_at. No NAV and no units
get_mutual_fund_ordersportfolio:readlimit (1 to 200, defaults to 50), cursor, period (7d, 30d, 90d, 1y or all), side, kind, state, broker, isin or schemeCode, sort (date or amount), dir (desc or asc), all optionalorders with order_id, isin, fund_name, side, kind, state, amount, units, allotment_nav, exchange_date and order_timestamp; summary with completed_purchase_total, completed_redemption_total, order_count and recorded_since; history_incomplete, next_cursor
list_watchlistswatchlist:readNo inputid, name, symbols, is_default, symbol_count, symbols_truncated. Tickers only, no prices.
list_alertswatchlist:readstatus (active or triggered), limit (1 to 200, defaults to 50), both optionalid, source, category, title, description, status, is_default, symbol, last_triggered_at, created_at
search_symbolswatchlist:readquery (1 to 64 characters, required), limit (1 to 50, defaults to 10)symbol, name, exchange, type, asset_class. Reference data only, with no price, volume or valuation field.
get_fundamentalsportfolio:readsymbols (1 to 25 NSE tickers from the holdings or the watchlists, optional; omit to read all of them)stocks with symbol, sector, industry, is_financial and metrics (field, label, value, unit, text, basis, as_of, source, missing_reason), symbols_without_data, symbols_not_in_account. Watchlist symbols need watchlist:read too.
list_saved_screenswatchlist:readNo inputid, name, universe, conditions, count and count_date of the latest nightly snapshot, changes_since_last_visit (entered, left), last_viewed_at, updated_at
list_familiesfamily:readNo inputhousehold_id, name, caller_consented. The household id the other two family tools require; no member is named and no value is reported.
get_family_overviewfamily:readhouseholdId (required)household_name, member_count, consented_member_count, total_value, holdings_count
get_family_exposurefamily:readhouseholdId (required), limit (1 to 25, defaults to 25)consented_member_count, symbols with value, weight_pct and holder_count, sectors with value and weight_pct

Scroll sideways to see every column.

There is no tool for placing, changing, or cancelling an order, and no tool that returns a market price for a symbol you do not hold. There is no positions tool either: positions live only in the broker's book, and serving them would mean calling the broker on every invocation, which the read-only design does not permit.

Scopes

Three scopes, granted separately on the consent screen. Scope is enforced before a tool runs, and a token sees only the tools its scopes reach: a client without portfolio:read does not find the portfolio tools in tools/list at all.

ScopeWhat you are approvingTools it unlocks
portfolio:readRead your holdings, mutual funds and SIPs, fund orders, portfolio value, risk metrics, and the stored fundamentals of those stocksget_portfolio_overview, get_holdings, get_allocation, get_portfolio_history, get_risk_metrics, list_broker_connections, get_mutual_fund_sips, get_mutual_fund_orders, get_fundamentals
watchlist:readRead your watchlists, price alerts, and saved screenslist_watchlists, list_alerts, search_symbols, list_saved_screens
family:readRead your family's combined exposure, for members who allowed itlist_families, get_family_overview, get_family_exposure

Scroll sideways to see every column.

Limits

Requests are counted against your token rather than your address, so one busy agent cannot exhaust another user's budget.

BucketLimitApplies to
General60 requests per 60 secondsEvery tool except the three analytics tools
Analytics10 requests per 60 secondsget_risk_metrics, get_portfolio_history, get_family_exposure

Scroll sideways to see every column.

Every list-returning tool has a hard row cap. When a cap bites, the result says so rather than trimming quietly.

ToolDefaultMaximum
get_holdings50200
get_mutual_fund_sips50200
get_mutual_fund_orders50200
search_symbols1050
get_fundamentalsAll account symbols, up to 2525 symbols
list_saved_screensAll25 screens, 50 symbols per change list
list_alerts50200
list_watchlistsAll50 lists, 200 symbols each
get_family_exposure2525
get_portfolio_historySet by range1,825 points

Scroll sideways to see every column.

Errors

Every failure carries a stable code and one human sentence. Only two are HTTP statuses: the transport refuses a request before it reaches a tool. The rest are tool errors inside a successful JSON-RPC response, so the status is 200 and the failure travels in the body as isError. Branching on res.ok alone will swallow four of the six. An account with nothing synced is not an error at all: the tool returns an empty result, an as_of of null, and a reason your assistant can read out.

CodeHTTPMeaning
unauthorizedHTTP 401The token is missing, expired, or was issued for another resource. Returned by the transport, with a WWW-Authenticate header
rate_limitedHTTP 429The bucket is exhausted. Returned by the transport, with Retry-After and X-RateLimit headers
insufficient_scopeTool error (HTTP 200)The token is valid but does not carry the scope the tool needs
not_foundTool error (HTTP 200)The household or watchlist id does not belong to the calling account
invalid_inputTool error (HTTP 200)The arguments failed schema validation. The SDK rejects these before the tool runs, so the message is its wording rather than ours
upstream_unavailableTool error (HTTP 200)A database or service read failed

Scroll sideways to see every column.

Calling a tool directly

Use an MCP client if you have one. If you are testing by hand, protocol revision 2026-07-28 rejects a request that omits the Mcp-Method header, omits Mcp-Name on a tool call, or omits the params._meta envelope carrying the protocol version. The errors it returns read like a malformed request rather than a missing header, so copy the example whole.

Terminal
curl https://arthaterminal.com/api/mcp \
  -H "Authorization: Bearer $ARTHA_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: get_portfolio_overview" \
  -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_portfolio_overview",
    "arguments": {},
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28"
      }
    }
  }'

Artha is operated by Quantrast Technologies Private Limited, CIN U66190MR2026PTC475667. Artha is not a SEBI-registered Investment Adviser or Research Analyst: no advice, no target prices, no recommendations. The server returns your own stored figures, each dated. Read the risk disclosure.

Something not working? A tool that answered wrongly, a client that will not connect, or a step above that does not match what you see.

We use analytics cookies to understand how you use Artha and improve your experience. No data is sold to third parties.