paper-broker-mcp
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., "@paper-broker-mcpbuy 10 shares of Reliance, show me the preview first"
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.
paper-broker-mcp
An MCP server for a simulated stock trading account, plus a small agent loop that talks to it. You say "buy 10 Reliance", the agent looks up the stock, previews the order, reads it back and asks "Shall I place it?". Only after you say yes does anything get placed.
This is the backend for the voice trading agent on my portfolio: https://www.anantdubey.com/work/voice-trading-agent. The idea comes from my Ideathon 2026 entry. This repo is a from-scratch rebuild done in public and shares no code with the original.
Prices are simulated and no real money is involved. It isn't connected to any broker or exchange, and nothing here is investment advice.
How it fits together
browser mic ──speech-to-text──┐ ┌── text-to-speech ──> speaker
v │
runAgentTurn(messages, state)
│
model (Claude, Gemini, or offline rules)
│ tool calls
v
MCP client ══ in-memory transport ══ MCP server
│
v
PaperBroker (plain JSON state)
prices = f(symbol, time)The same MCP server also runs over stdio, so Claude Desktop or any other MCP client can use it directly.
Related MCP server: trclient-mcp
Tools
Tool | What it does |
| Turns a spoken name ("state bank", "L and T", "infy") into an NSE symbol. |
| Last price, previous close, change, day high and low. Always marked |
| Cash, cash blocked by open buy orders, available cash, holdings value, P&L. |
| Holdings with average price, current price and P&L. |
| Recent orders, newest first. |
| Checks an order and returns |
| Places a previewed order. Fails if the preview doesn't exist or has expired. |
| Cancels an open limit order. |
Each tool returns a short text line (written to be read aloud) and the same data as structured JSON.
Preview, then confirm
There is no tool that places an order from raw parameters. An order can only come from a preview, and a preview only lives for 60 seconds. That gives two layers of protection:
The server.
place_ordertakes nothing but apreview_id. The model can't invent an order the user never heard, and a stale preview can't be replayed. Its description says to call it only after the user has explicitly confirmed the preview.The agent loop.
runAgentTurnonly letsplace_orderthrough for the preview that was pending before the user's latest message. A preview created during the current turn is refused withNOT_CONFIRMED, whatever the model decides, so the user always hears the preview and answers before anything is placed. If the user says anything other than a confirmation, the pending preview is dropped.
Quickstart
Claude Desktop
Add this to claude_desktop_config.json and restart Claude Desktop:
{
"mcpServers": {
"paper-broker": {
"command": "npx",
"args": ["-y", "github:dubeyanant/paper-broker-mcp"]
}
}
}The account lives in memory and resets when the server restarts. To keep it, add "--state", "/path/to/paper-account.json" to args. The file is created on the first change.
Terminal chat
git clone https://github.com/dubeyanant/paper-broker-mcp
cd paper-broker-mcp
npm install
npm run chatTool calls are printed dimmed above each reply. Things to try: buy 10 reliance, yes, sell 5 TCS at 4,000, buy twenty shares of infosys, price of HDFC bank, how is Tata Motors doing, show my portfolio, how much cash do I have, my orders, cancel my last order. Add -- --provider rules to force the offline parser.
The chat script and tests run the TypeScript sources directly, which needs Node 22.18 or newer. The built package in dist/ runs on Node 20.
From code
import { runAgentTurn } from "paper-broker-mcp/agent";
const first = await runAgentTurn({
messages: [{ role: "user", content: "buy 10 reliance" }],
state: null, // fresh account with 10 lakh rupees of virtual cash
});
first.reply; // "Buy 10 shares of Reliance at market, about 29,425 rupees. Shall I place it?"
first.events; // [{ type: "tool_call", name: "search_instruments", args: {...} }, { type: "tool_result", ... }, ...]
const second = await runAgentTurn({
messages: [...first.messages, { role: "user", content: "yes" }],
state: first.state, // plain JSON, safe to store anywhere between turns
});
second.reply; // "Done. Bought 10 shares of Reliance at 2,942 rupees 45 paise."state is plain JSON, so a web route can send it to the browser and get it back on the next request. Validate before trusting it: runAgentTurn and PaperBroker.fromState both reject malformed state.
The broker and server are available on their own too:
import { PaperBroker, createServer } from "paper-broker-mcp";
const broker = PaperBroker.fromState(savedState); // or null
const server = createServer(broker); // an McpServer; connect it to any transport
// ...after tool calls:
const next = broker.toState();API keys
Copy .env.example to .env. Every value is optional.
Variable | Default | Notes |
| Uses Claude when set. | |
|
| |
| Uses Gemini when set and there is no Anthropic key. | |
|
|
Either key works. With neither, the agent uses a built-in rules parser that makes no network calls and drives the same MCP tools, so the events look the same. If a model call fails before any tool has run, the turn is answered by the rules parser and the result includes an error field.
How the simulation works
Universe. Twenty NSE large caps, each with spoken aliases ("RIL", "tata consultancy", "airtel", "L and T"). Equity delivery only.
Prices. A pure function of symbol and time: a base price times a sum of slow sine waves (periods from 47 minutes to 71 days, with per-symbol phases) plus a little hashed noise that changes once a second, rounded to the 0.05 tick. Nothing is stored, so any process computes the same price for the same second. The market never closes; "previous close" is the price just before midnight IST.
Account. Starts with 10 lakh rupees of virtual cash. No brokerage, taxes or slippage.
Rules. Quantity 1 to 10,000. Buys need enough available cash. No short selling. Limit prices must be within 20% of the last price. Market orders fill at the last price. Limit orders rest, block cash (buys) or shares (sells), and fill at the limit price the first time the price path touches it. Open orders are checked whenever the account is used, by walking the price path since the order was placed.
Development
npm test # node:test, runs the TypeScript sources directly
npm run typecheck # src, tests and examples
npm run build # compile src to dist/dist/ is committed on purpose so the package can be installed straight from GitHub without a build step. Run npm run build and commit the result after changing anything in src/.
Disclaimer
Simulated prices, no real money, not investment advice. This project is not affiliated with any broker or exchange. Stock names and symbols are used only to make the demo recognisable.
License
MIT. See LICENSE.
Available Tools
8 toolscancel_orderCancel orderADestructive
Cancel an open limit order by its id, for example ORD-3. Filled orders cannot be cancelled.
| Name | Required | Description | Default |
|---|---|---|---|
| order_id | Yes | Order id from get_orders or place_order, for example ORD-3. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation risk is covered structurally. The description adds the useful eligibility rule about filled orders, but says nothing about side effects such as fund release, partial fills, or what confirmation is returned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the core action first and the constraint second; no filler and nothing buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-required-parameter mutation with no output schema and full annotation coverage, the description covers the operation and its key eligibility constraint. Only the post-cancellation outcome is left unstated, which is minor here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents order_id with its source (get_orders or place_order) and the ORD-3 example. The description's mention of the id and example duplicates rather than extends the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Cancel an open limit order') with a scope qualifier that separates it from the read/place/preview siblings. It does not name a sibling explicitly, but the action is unambiguous against get_orders and place_order.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear precondition (order must be open) and an explicit exclusion ('Filled orders cannot be cancelled'), which is the main failure mode for this call. No alternative tool is named, though no sibling offers cancellation, so nothing critical is omitted.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fundsGet fundsBRead-only
Cash, cash blocked by open buy orders, available cash, holdings value and profit or loss for the account.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds value by enumerating the concrete fields returned, which is useful because there is no output schema, but it says nothing about freshness, currency/unit of the amounts, or whether blocked cash reflects live open orders.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence with no padding, but it is a noun-phrase fragment lacking a leading verb, so the agent must infer the action. Efficient but under-specified rather than well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-param, read-only tool with no output schema, disclosing the returned fields is the right move and is done. However, the missing action verb and the absence of any scoping (currency, account selection implied only by session context) leave the definition merely adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so there is nothing for the description to compensate for. Baseline 4 applies; the schema is trivially complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The sentence enumerates the data returned (cash, blocked cash, available cash, holdings value, P/L) 'for the account,' which implies an account-balance retrieval, but never states a verb or resource like 'retrieve account funds summary.' It also does nothing to distinguish it from siblings such as get_positions or get_orders, which overlap on account-level data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to call this versus get_positions (which also reports holdings value) or get_orders. No preconditions, no exclusions, no alternatives named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ordersGet ordersBRead-only
Recent orders, newest first, with status (OPEN, FILLED, CANCELLED or REJECTED).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds the sort order and the enumerated status values, but leaves 'recent' undefined — no count, window, or truncation behavior — which matters for a read tool returning a list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single clause, front-loaded with the resource and ordering, with zero filler. Nothing redundant relative to the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description is the only source for return semantics; it covers fields and statuses but not how many orders are returned or how 'recent' is bounded. Adequate for a no-parameter reader, but the result-set size gap is a real omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. It correctly signals the tool takes no filters, which implicitly tells the agent it cannot scope by instrument or date.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete resource (orders) and its ordering (newest first) plus the status domain, which distinguishes it from mutation siblings like place_order and cancel_order. It never explicitly names a sibling or says 'retrieves order history', but the returned content is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to call this versus preview_order or the other read siblings, and no exclusions or prerequisites. Usage is only implied by the description of returned data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_positionsGet positionsARead-only
Stocks held in the account with quantity, average price, current price and profit or loss.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds value by enumerating the returned fields, which matters because there is no output schema. However, it says nothing about freshness/real-time behavior, whether cash or non-stock assets are included, or whether the list can be empty — meaningful gaps for a portfolio read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that leads with what is returned and then lists the fields. No filler, no repetition of the title, nothing that could be cut.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool with annotations covering safety and no output schema, the description's field enumeration largely carries the return-value burden. The remaining gap is the boundary with get_funds and get_orders, which an agent must guess at when assembling a portfolio view.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there is nothing for the description to disambiguate. It correctly implies the call is account-scoped with no filtering knobs, which matches the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the specific resource (stocks held in the account) and enumerates the returned fields (quantity, average price, current price, profit or loss), which is far more informative than the name alone. It implicitly distinguishes from get_funds (cash) and get_orders (order history), but never names those siblings or explicitly contrasts with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent can infer this is the tool for checking current holdings, but there is no explicit when-to-use, no exclusions, and no pointer to alternatives such as get_funds or get_orders when position data is not what's needed. Adequate but with a clear routing gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_quoteGet quoteARead-only
Current simulated price for one stock: last price, previous close, day change, day high and low.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | NSE symbol, for example RELIANCE. Use search_instruments if unsure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description's one real addition is 'simulated', signalling this is paper-trading data rather than live market prices — a meaningful trait not in the annotations, though latency/staleness and error behavior for invalid symbols are unstated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence with zero filler, leading with the core purpose and then the returned fields. It is a fragment without an explicit verb phrase ('Returns...'), a minor stylistic gap rather than a substantive one.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with full schema coverage and annotations covering safety, the description is nearly sufficient: it names the data source ('simulated') and enumerates the five returned values, substituting for the absent output schema. Only symbol-validation failure behavior is left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the symbol parameter is fully documented, including the search_instruments fallback. The description only reinforces that exactly one symbol is accepted ('one stock') and that the price is current rather than historical, adding marginal value over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource ('Current simulated price for one stock') and enumerates the returned fields, so the agent knows exactly what it gets. It does not name or differentiate itself from siblings like get_positions or preview_order, but the domain distinction is obvious.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied — the agent infers 'call this when you need a price for a single symbol'. There is no explicit when-to-use/when-not statement and no pointer to alternatives; the useful 'use search_instruments if unsure' hint lives in the schema, not the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
place_orderPlace orderA
Place an order from a preview made by preview_order. Call only after the user has explicitly confirmed the preview (for example 'yes' or 'go ahead'). Never call it in the same step as preview_order. Fails if the preview does not exist or has expired.
| Name | Required | Description | Default |
|---|---|---|---|
| preview_id | Yes | The preview_id returned by preview_order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the mutation profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), so the description's added value is the failure conditions ('fails if the preview does not exist or has expired') and the human-confirmation gate, which an agent would otherwise not know. It stops short of describing resulting order state or how duplicate submissions behave, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences: what it does, the required human confirmation, the sequencing prohibition, and the failure mode. No filler, and the prerequisite is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter mutation with no output schema and annotations covering the safety profile, the description supplies everything an agent needs: the source of the ID, the confirmation gate, the ordering constraint relative to preview_order, and failure conditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single preview_id is documented in the schema, so the baseline is a 3; the description adds meaning by tying the ID to preview_order and declaring that stale/nonexistent preview IDs cause failure, which is a real validity constraint beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('place an order') and ties it directly to its generating sibling ('from a preview made by preview_order'), which cleanly separates it from preview_order and cancel_order without needing the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit precondition (user must have explicitly confirmed the preview, with example affirmations), an explicit prohibition ('never call it in the same step as preview_order'), and the alternative to use first (preview_order). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preview_orderPreview orderA
Check an order and get a preview to read back to the user. Does not place anything. Returns a preview_id that place_order needs. Previews expire after 60 seconds.
| Name | Required | Description | Default |
|---|---|---|---|
| side | Yes | BUY or SELL. Selling more than you hold is not allowed. | |
| symbol | Yes | NSE symbol, for example RELIANCE. | |
| quantity | Yes | Number of shares, 1 to 10000. | |
| order_type | Yes | MARKET fills now at the last price. LIMIT waits for the price to reach limit_price. | |
| limit_price | No | Required for LIMIT orders. Must be within 20% of the last price. Rounded to the 0.05 tick. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavioral context beyond the annotations: it does not transact, it produces a preview_id consumed downstream, and the preview expires after 60 seconds — a time limit that materially affects agent sequencing. No contradiction with readOnlyHint=false, since the tool does create server-side state (the preview token).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action, then the safety negation, then the output contract and its expiry. No sentence is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the critical facts for a preview tool with no output schema: it is non-committal, returns preview_id, and the token is time-limited. Slightly incomplete in that it doesn't say what the preview contains to read back (price, charges, validity), which the agent must discover at runtime.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3; the description goes slightly beyond by naming the returned identifier and its downstream consumer. It still says nothing about how symbol/side/quantity/order_type interact, but the schema already carries units, ranges and enum meanings.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Check an order and get a preview') with an explicit negation of the adjacent write operation ('Does not place anything'), which cleanly separates it from place_order. An agent can pick this tool over any sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Establishes the workflow position by stating the returned preview_id is what place_order needs, so the agent knows this is the required precursor. It doesn't spell out edge cases (e.g. what to do if the preview expires mid-flow, or when re-preview is needed), keeping it short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_instrumentsSearch instrumentsARead-only
Find NSE stocks by company name, spoken name or symbol (for example 'reliance', 'state bank', 'L and T', 'infy'). Use this to turn what the user said into a symbol before quoting or ordering.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Company name, nickname or symbol, as the user said it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false; the description usefully reinforces the closed NSE universe and the tolerance for spoken/nickname forms. It does not disclose what comes back (single best match vs. ranked list) or what happens on ambiguous or zero-result queries, which is the main behavioral unknown for a search tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler. The capability statement comes first, the usage directive second, and the examples are embedded inline rather than in a separate list.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter lookup with no output schema, the description covers input well but says nothing about the result shape or ambiguity handling. An agent knows how to call it but not whether to expect one instrument or a candidate list, which affects whether it must confirm with the user.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the examples add real meaning beyond the schema: they show that phonetically-spelled or transliterated forms ('L and T', 'infy', 'state bank') are legitimate queries. That is exactly the kind of guidance an agent needs when converting speech to a query string.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Find NSE stocks") and enumerates the three matching keys: company name, spoken name, symbol. Concrete query examples ('reliance', 'L and T', 'infy') make it unmistakable against siblings like get_quote or get_orders.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use this to turn what the user said into a symbol before quoting or ordering" gives a clear triggering condition and implicitly points at get_quote/place_order as downstream tools. It stops short of naming those siblings or saying when not to use it (e.g. when a symbol is already known), so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
cancel_order - First observed
get_funds - First observed
get_orders - First observed
get_positions - First observed
get_quote - First observed
place_order - First observed
preview_order - First observed
search_instruments
TDQS
Scored across 8 tools
Each tool targets a distinct resource+action pair: search_instruments resolves names to symbols, get_quote prices a single stock, get_funds/get_positions/get_orders read distinct account views, and cancel_order/preview_order/place_order cover separate order lifecycle steps. The preview_order/place_order split is explicitly documented as a two-step gate with a preview_id handshake, so misselection risk is low. No two tools appear to do the same thing.
Every tool is snake_case verb_noun (search_instruments, get_quote, get_funds, get_positions, get_orders, preview_order, place_order, cancel_order). The verb choices are meaningful and predictable: get_* for reads, preview/place/cancel_* for lifecycle actions. No mixed conventions or vague verbs.
Eight tools is well-scoped for a paper-trading broker: three read-only account views, one instrument lookup, one quote, and a three-step order lifecycle. Each tool earns its place and there is no filler or redundant surface.
The surface covers the full retail trading loop: discovery (search_instruments), pricing (get_quote), account state (funds/positions/orders), and order creation and cancellation with a preview gate. Minor gaps remain, such as no modify-order operation, no single-order status lookup by id, and no market-hours/status signal, but agents can work around these using get_orders and cancel-then-replace.
Maintenance
Related MCP Connectors
- FensoryOAuthcom.fensory
Trading MCP server for AI agents, with live market data, account reads and controlled execution.
NSE/BSE stock data via Tickertape as JSON: index lists, screener, 10-year fundamentals.
Open-source MCP server for Zerodha Kite Connect. Portfolio, market data, backtesting, alerts.
Paper trading for AI: live quotes, indicators, and virtual trades on stocks, crypto, and forex.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceEnables language models to trade on a Zerodha account by placing and canceling orders and reading orders and portfolio positions over stdio.-
- AlicenseAqualityBmaintenanceEnables local management of Trade Republic accounts, including portfolio, cash, orders, documents, and market data, with dry-run order previews and safety guardrails.22MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to connect to brokerage accounts in read-only mode so users can inspect balances, positions, and orders, and provides a local lab for backtesting strategies and simulated trading with pretend money.MIT
- AlicenseNot gradedqualityAmaintenanceEnables reading a Trading 212 Stocks ISA and safely previewing, approving, placing, and cancelling orders, with account, position, order-history, and instrument-search tools.MIT