Local options pricing for Excel and AI agents — HTTP API and MCP server for Greeks, IV, and PnL attribution
DeskPricer demonstrates strong domain-specific tool design with comprehensive parameter schemas and detailed descriptions. All 4 tools have explicit JSON schemas with proper type definitions and required/optional field declarations. Descriptions are lengthy (200-400+ chars) and include usage context, unit conventions, and engine/calendar support. However, parameter descriptions within schemas are minimal (often 1-2 words), and tool names lack action verbs (price_option, implied_volatility, pnl_attribution, portfolio_greeks are domain-specific but not verb-noun patterns). Error handling and output schema documentation are absent from visible code. No tool annotations (readOnlyHint, destructiveHint) despite all being READ_ONLY operations.
Solve for Black implied volatility given an observed option market price. HTTP equivalent: GET /v1/impliedvol Use to back out vol from a quoted premium. IV solving uses QuantLib (analytic for european, binomial for american). Reprices at the solved vol when verify_reprice=true (default). Units: rates/q/v/b are decimals (0.05 = 5%, 0.20 = 20% vol). t is ACT/365 years (floored to 1 calendar day). Outputs are per 1 option contract (qty=1). vega and rho are per 1% point; theta and charm are per 1 calendar day. Engines: european requires engine=analytic (default). american uses binomial_crr (default) or binomial_jr. Americans economically equal to Europeans are auto-priced via closed-form BSM (calls when |q+b|≤1e-8; puts when |r|≤1e-8). Calendars: hong_kong (default), us_nyse, us_settlement, united_kingdom, null. Required: s, k, t, r, q, price (observed premium), type, style. Optional: b, engine, steps, valuation_date, calendar, accuracy, max_iterations, verify_reprice. Returns JSON: {"impliedvol":{"meta":{...}, "inputs":{...}, "outputs":{implied_vol, npv_at_iv}}}.
Decompose option PnL between two market snapshots into Greek buckets. HTTP equivalent: GET /v1/pnl_attribution Use after a move in spot, vol, rates, or time to explain actual PnL vs delta/gamma/vega/theta/rho (and optional vanna/volga). All outputs are per unit; multiply by qty yourself for position size. Units: rates/q/v/b are decimals (0.05 = 5%, 0.20 = 20% vol). t is ACT/365 years (floored to 1 calendar day). Outputs are per 1 option contract (qty=1). vega and rho are per 1% point; theta and charm are per 1 calendar day. Engines: european requires engine=analytic (default). american uses binomial_crr (default) or binomial_jr. Americans economically equal to Europeans are auto-priced via closed-form BSM (calls when |q+b|≤1e-8; puts when |r|≤1e-8). Calendars: hong_kong (default), us_nyse, us_settlement, united_kingdom, null. Required: s_t_minus_1, s_t, k, t_t_minus_1, t_t (must not increase), r/q/v at both dates, type, style. Optional: b_t_minus_1, b_t, engine, steps, qty (accepted but does not scale per-unit outputs), valuation_date_t_minus_1 / valuation_date_t (ISO; both or neither — default today with 1 calendar day elapsed), method (backward|average for vega/rho), cross_greeks (add vanna/volga buckets), calendar, bump_*. Theta PnL = theta × calendar_days between valuation dates. Vega/rho use vol/rate changes in percentage points. Returns JSON: {"pnl_attribution":{"meta":{..., calendar_days, method}, "inputs":{...}, "outputs":{price_t_minus_1, price_t, actual_pnl, delta_pnl, gamma_pnl, vega_pnl, theta_pnl, rho_pnl, vanna_pnl, volga_pnl, explained_pnl, residual_pnl}}}.
Tool names lack action verbs. 'price_option', 'implied_volatility', 'pnl_attribution', 'portfolio_greeks' are domain-specific but do not follow verb_noun pattern (get_, calculate_, compute_). LLMs infer intent from verb, these names require reading full descriptions.
Parameter descriptions in JSON schemas are minimal (1-2 words: 'Spot price', 'Strike price'). Rubric baseline: 72 chars average. These lack format guidance, constraints, and context. E.g., 'Spot price' should be 'Spot price (positive number, e.g., 100.50 for equity or 45000 for crypto)'.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite all tools being READ_ONLY. Current MCP spec (2026-07-28) supports tool annotations for agent safety, these should be declared.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 58 | <=2025-11-25 | v2 |
Price up to 500 option legs and return per-leg Greeks plus qty-weighted aggregate. HTTP equivalent: POST /v1/portfolio/greeks Use for spreads, baskets, or any multi-leg structure. Each leg carries its own spot/strike/vol and optional qty (negative for short). Leg outputs are unit Greeks; aggregate sums qty × greek across legs. Units: rates/q/v/b are decimals (0.05 = 5%, 0.20 = 20% vol). t is ACT/365 years (floored to 1 calendar day). Outputs are per 1 option contract (qty=1). vega and rho are per 1% point; theta and charm are per 1 calendar day. Engines: european requires engine=analytic (default). american uses binomial_crr (default) or binomial_jr. Americans economically equal to Europeans are auto-priced via closed-form BSM (calls when |q+b|≤1e-8; puts when |r|≤1e-8). Calendars: hong_kong (default), us_nyse, us_settlement, united_kingdom, null. Required: legs[] — each leg needs id, qty, s, k, t, r, q, v, type, style (plus optional b, engine, steps, calendar, underlying_id, bump_*). Optional: valuation_date (ISO, default today). Warns (does not fail) if legs sharing underlying_id have spot prices diverging by >5%. Returns JSON: {"portfolio":{"meta":{service_version, quantlib_version, valuation_date}, "legs":[{id, engine, price, delta, ...}], "aggregate":{price, delta, gamma, vega, theta, rho, charm}}}.
Price one vanilla equity option and return price plus full Greeks. HTTP equivalent: GET /v1/greeks Pricing: europeans (and equivalent americans) use closed-form BSM; other americans use QuantLib binomial CRR/JR. Use when marking a single call/put, checking sensitivities, or as input to your own risk logic. For multi-leg books use portfolio_greeks. Units: rates/q/v/b are decimals (0.05 = 5%, 0.20 = 20% vol). t is ACT/365 years (floored to 1 calendar day). Outputs are per 1 option contract (qty=1). vega and rho are per 1% point; theta and charm are per 1 calendar day. Engines: european requires engine=analytic (default). american uses binomial_crr (default) or binomial_jr. Americans economically equal to Europeans are auto-priced via closed-form BSM (calls when |q+b|≤1e-8; puts when |r|≤1e-8). Calendars: hong_kong (default), us_nyse, us_settlement, united_kingdom, null. Required: s (spot), k (strike), t, r, q, v (vol), type (call|put), style (european|american). Optional: b (borrow cost, default 0), engine, steps (american tree, default 500), valuation_date (ISO, default today), calendar, bump_spot_rel / bump_vol_abs / bump_rate_abs (american bump-and-revalue only). Returns JSON: {"greeks":{"meta":{service_version, quantlib_version, engine, valuation_date}, "inputs":{...}, "outputs":{price, delta, gamma, vega, theta, rho, charm}}}.
Output schemas not documented in tool descriptions. Agents cannot plan downstream calls without knowing return structure. E.g., 'Returns JSON: {greeks: {meta, inputs, outputs}}' is present but lacks field-level type info.
No error handling guidance visible. Tools accept complex financial parameters (rates, vols, dates) with no validation error messages documented. E.g., if t_t > t_t_minus_1 in pnl_attribution, what error is returned? How should agent recover?