Files
Danglewood bbf1ab2020 V5 (#7489)
* [Feature] OpenBB V5: Initial `openbb-core` Refactor (#7482)

* initial refactor

* ruff does not dictate style

* unresolved imports in test action

* fix general linting

* resolve pandas imports for actions run

* httpx in test workflow

* pytest-asyncio in test workflow

* pandas.Index(...)

* max version for windows CI is 3.14

* remove temp refactor files that shouldn't have been committed:

* use ruff format instead of black

* formatting and typing

* tab space helper

* test fixtures..

* ty check

* also run integration test in CI

* remove that annoying labeler action

* [V5] `openbb-core`: 100% Test Coverage (#7484)

* increase test coverage to exercise 100% of the testable code path in openbb-core

* model_fields syntax cleanup

* set the environment variable for CI runs

* run codeql on v5 branch

* more CI env setup

* cleanup redundant files

* ruff

* dedupe workflow trigger

* some windows coverage missing

* ubuntu integration test job

* more windows coverage

* test_reference_generator

* test_docstring_generator

* remove line no references from test function docstrings

* clean useless comments from test files

* fix polars type check

* fix test_obbject

* fix test_obbject

* package builder fixes

* charting pyproject version

* fix docstring generator for nested models

* missing coverage

* [V5] `openbb-core`: Add Backwards-Compatible Layered Config System (openbb.toml) (#7492)

* add backwards-compatible layered config system

* fix path reference in windows test

* need python version-aware handling in docstring generator

* update for deprecated pydantic syntax

* ruff UP007

* test_system_settings

* remove v4 platform workflow

* [V5] Refactor `openbb-oecd` for full SDMX 2 API Exposure and V5 Packaging (#7413)

* stash some changes

* add more robust testing

* mypy

* point PR at V5

* introduce spec file

* codespell

* test fix

* fix workflow environment setup

* fix workflow environment setup

* fix workflow environment setup

* add pyyaml to dependencies

* split lint jobs

* fix workflow environment setup

* fix workflow environment setup

* workflow env setup

* workflow env setup

* clean up code comments

* add auth hook entrypoints

* codespell

* add codegen feature

* codespell

* move _unpack into dispatchers for consistency with codegen packages

* surface nested models in the response

* fix missing coverage in CI

* socrata updates

* test fix

* detect plotly output

* add --include and --exclude flags from generate-extension command

* refactor openbb-platform-api for V5 operations and spec file handling

* delete poetry.lock

* add test workflow

* add temp branch id for test workflow

* add httpx to dev dependencies

* add a conftest.py

* tweak conftest

* tweak conftest

* python 3.10 issues

* more python 3.10

* more python 3.10

* more python 3.10

* more python 3.10

* fix url template resolution

* multi-spec support

* fix a windows path issue

* merge branch develop

* table builder, integration tests, and more

* linting

* merge branch develop

* bit of cleanup

* some more updates, cleanup, and apps.json

* codespell

* black

* integration test params and linting

* mypy

* pylint

* black

* more pylint

* recapture teest cassettes

* black again

* more linting

* table presentation choices

* black

* fix merge conflict

* split up metadata module and reformat cache to use msgpack

* mypy

* regenerate lock file

* use json and include dependencies to make openbb-oecd a standalone install

* pylint

* more linting

* serve metadata as dependency instead of assign and initialize

* fix integration_tests_testers to not count dependency injections as paramters

* add assets to git ignore

* ruff

* v5 refactor and publish workflow

* test coverage and ty fixes

* codespell

* update lock file

* workflow setup

* ty check

* workflow setup

* Scope PR to OECD changes only

Restore non-OECD files in the diff against v5 to their v5 state. The
branch was originally created off feature/cli-2 and inherited 186 files
of unrelated changes (cli, agent_server, mcp_server, platform_api,
core/, .github/workflows/* not oecd). Those have nothing to do with the
openbb-oecd v5 refactor and were polluting the PR diff.

* scope cleanup: include leaked v5-resident files (general-linting workflow, platform_api test fixtures)

---------

Co-authored-by: deeleeramone <>
Co-authored-by: Copilot <copilot@github.com>

* fix docstring generator and body param unwrapping

* project ty.toml file

* unpack POST parameters from params: Model

* remove comment chatter

* [V5] `openbb-oecd`: Rename `oecd_utils` as `oecd` (#7509)

* rename oecd_utils to oecd and populate all models there when openbb-economy is not installed

* linting

* bump dependencies

* fix test drift

* linter

* FieldInfo import

* [V5] `openbb-imf`: Refactor for V5 (#7508)

* refactor imf extension for V5

* codespell

* fix some python 3.10 items

* return self on copy of metadata object

* [V5] `openbb-news`: Refactor News for V5 and Add Configurable RSS Endpoint (#7507)

* refactor news for v5 and add rss endpoint

* remove poetry.lock

---------

Co-authored-by: deeleeramone <>

* [V5] `openbb-quantitative`: Refactor for V5 (#7506)

* refactor quantitative for v5

* add factors endpoint and add a few charts

---------

Co-authored-by: deeleeramone <>

* [V5] `openbb-technical`:  Refactor for V5 & Add More Quick Win Endpoints (#7502)

* refactor openbb-technical for v5

* forward refs

* linting

* no python 3.15 in test matrix

* reame

* ty

* move all params to body

---------

Co-authored-by: deeleeramone <>

* remove stockgrid provider (#7486)

* [V5] remove wsj provider and related code (#7485)

* remove wsj provider and related code

* purge from metadata

* actions

* actions

* openbb-core publish workflow

* delete biztoc (#7523)

* [V5] Remove `openbb-alpha-vantage` (#7522)

* delete alpha vantage

* more files

---------

Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>

* [V5] Remove `openbb-benzinga` (#7521)

* delete benzinga

* more references

---------

Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>

* [V5] `openbb-bls`: Refactor for V5 + Add Many Endpoints (#7518)

* refactor bls for v5, add 100 widgets

* some CI fixes

* no python 3.15

* fix missing dev group in pyproject.toml

* more pyproject fallout

* action

* refactor econometrics for v5 (#7505)

Co-authored-by: deeleeramone <>

* [V5] `openbb-famafrench`: Refactor for V5 (#7503)

* refactor famafrench for v5

* codespell

* finishing touches

---------

Co-authored-by: deeleeramone <>

* [V5] CLI 2.0 - Pluggable Backends, Non-TTY Default, HTTP Dispatcher, Spec Files + Codegen (#7433)

* stash some changes

* add more robust testing

* mypy

* point PR at V5

* introduce spec file

* codespell

* test fix

* fix workflow environment setup

* fix workflow environment setup

* fix workflow environment setup

* add pyyaml to dependencies

* split lint jobs

* fix workflow environment setup

* fix workflow environment setup

* workflow env setup

* workflow env setup

* clean up code comments

* add auth hook entrypoints

* codespell

* add codegen feature

* codespell

* move _unpack into dispatchers for consistency with codegen packages

* surface nested models in the response

* fix missing coverage in CI

* socrata updates

* test fix

* detect plotly output

* add --include and --exclude flags from generate-extension command

* cap test matrix at python 3.14

* no useless comments

* platform controller command description split

* merge URL overloads from path params

* exclude none and unset from model dump

---------

Co-authored-by: deeleeramone <>
Co-authored-by: Copilot <copilot@github.com>

* general-linting

* downgrade aiohttp in devtools for vcrpy

* some ty items and add requests-types stubs for ty in devtools

* markdown linting

* remove integration tests from extensions that were moved into the famafrench provider

* [V5] `openbb-congress-gov`: Refactor for V5 + Convert To Using Bulk Files Instead of `api.congress.gov`. (#7528)

* refactor congress-gov for v5 and use bulk files instead of API with credentials

* integration tests

* apps tab name

* convert caching to sql

* codespell

* [V5] [BugFix] Fix for Breaking Changes in FastAPI 0.137+ (#7537)

* fix route introspection for fastapi 0.137

* recapture oeccd gdp forecast test cassette

---------

Co-authored-by: deeleeramone <>

* [V5] `openbb-platform-api`: Refactor for V5 Spec, Config, Packaging, Test Coverage (#7494)

* stash some changes

* add more robust testing

* mypy

* point PR at V5

* introduce spec file

* codespell

* test fix

* fix workflow environment setup

* fix workflow environment setup

* fix workflow environment setup

* add pyyaml to dependencies

* split lint jobs

* fix workflow environment setup

* fix workflow environment setup

* workflow env setup

* workflow env setup

* clean up code comments

* add auth hook entrypoints

* codespell

* add codegen feature

* codespell

* move _unpack into dispatchers for consistency with codegen packages

* surface nested models in the response

* fix missing coverage in CI

* socrata updates

* test fix

* detect plotly output

* add --include and --exclude flags from generate-extension command

* refactor openbb-platform-api for V5 operations and spec file handling

* delete poetry.lock

* add test workflow

* add temp branch id for test workflow

* add httpx to dev dependencies

* add a conftest.py

* tweak conftest

* tweak conftest

* python 3.10 issues

* more python 3.10

* more python 3.10

* more python 3.10

* more python 3.10

* fix url template resolution

* multi-spec support

* fix a windows path issue

* cap test matrix at python 3.14

* no 3.15 runners for platform-api

* no useless comments

* platform controller command description split

* merge URL overloads from path params

* exclude none and unset from model dump

* markdown lint

* ignore get/post endpoints that are return SSE

* fix remaining fastapi 0.137 fallout

---------

Co-authored-by: deeleeramone <>
Co-authored-by: Copilot <copilot@github.com>

* add full support for AsyncIterator response type for streaming output (#7530)

* [V5] Refactor Shared Pass Through Router Extensions For Hatchling (#7524)

* refactor shared pass-through routers for hatchling and ruff + ty

* add publish workflows

* [V5] `openbb-charting`: Refactor for V5 and Decouple  (#7545)

* refactor charting for v5 patterns and decouple entirely

* coveragerc

* lint and tests

* fix tests

* configure dev group with openbb-technical

* ty

* fix cli test

* remove 3.15 from test matrix - dependencies are unstable

---------

Co-authored-by: deeleeramone <>

* fix merge widgets

* workflow cleanup"

* fixes for ty

* fogot that file

* general lint setup

* consolidate lint job

* remove seeking alpha provider (#7570)

* remove tradier provider (#7573)

* remove tiingo provider (#7574)

* remove intrinio provider (#7575)

Remove the openbb-intrinio provider extension from the repository.
Reason: proprietary vendor with no internal access to any endpoint;
cannot build, develop or maintain.

* remove yfinance provider from repo (#7576)

* fix(cli): resolve modular OpenAPI references (#7586)

Fixes #7585

* [V5] `openbb-cli`: Modular OpenAPI Refs (#7589)

* follow up to #7585

* add another codegen test

* unused ty ignore

* Update generated tests to get python parameter names instead of raw API-provider parameter names. (#7597)

* Update the record-vs-envelope heuristic in the payload processing code to not treat a record that happens to have a list datatype as an entire envelope. (#7598)

* Update class generation code to handle empty data that php-style serialization emits as []. (#7599)

* fix ty check failures exposed by newer version

* add drugs.com and brutalist as news rss feeds (#7602)

Co-authored-by: deeleeramone <>

* codespell

* missing test coverage that appeared in famafrench..

* plotly 7 handling for mapbox namespace change

* remove finviz (#7577)

* remove trading economics provider (#7578)

* remove openbb-multpl from repository (#7610)

* add httpx2 to devtools for starlette test client

* restore test coverage to 100% in openbb_core

* remove fmp provider extension from repository (#7665)

* unpin ruff

* fix charting conftest and missing coverage in 3.10

* add charting coverage

* fix new ty issues

* fix tag grouping in swagger docs

* [V5] `openbb-ecb`: Refactor for V5 and Expand Coverage (#7560)

* refactor openbb-ecb for v5 and expand coverage

* some updates

* tests

* workflow

* remove 3.15 from test matrix

* some more table schema updates

* remove some html chrome on embedded articles

---------

Co-authored-by: deeleeramone <>

* [V5] `openbb-federal-reserve`: Refactor for V5 + FFIEC & Regional Fed Routers (#7561)

* refactor for v5

* add workflows

* fix bhcpr schema

* fix pyproject.toml

* fix test

* codespell

* ty

* fix pyproject

* fix ci environment

* fix ci environment

* convert documents endpoints to use fedinprint service

* codeql fix

* fix ny publications and add ny nowcast

* [V5] `openbb-eia`: Refactor for V5 + Add Full API Implementation (#7584)

* eia refactor for v5

* add test and publish workflows

* data browser state

* fix workflows

* more workflow test items

* temp files in tests

* more fixes

* more browsers

* fix codeql issues

* fix mer state and ensure multi-user capability

* uv lock

* table bridge

* fix electricity browser state

* convert HTML widgets to iFrame

* fix recursion error in workspace mcp

* [V5] `openbb-government-us`: Refactor for V5 + Move `uscongress` (#7604)

* v5 government_us provider

* workflow files

* ty and add xlrd to pyproject

* shrink test cassettes

* dev dependencies

* wheel packaging and more tests

* python 3.10 thing..?

* fix test

* default state for multiselect dropdowns

* replace congress html widgets with iframes

* fallback to congress api for congress before 108

* ensure member passage voting count populates

* [V5] Feature: Add JODI World Oil & Gas Database (#7593)

* add the JODI oil and gas database as a provider/router extension

* lint fixes

* add grouping to apps.json

---------

Co-authored-by: deeleeramone <>

* [V5] `openbb-cftc`: Refactor for V5 + Add OIS, Forward Curve, and FX Trade Analysis (#7615)

* refactor openbb-cftc for v5

* add SHIBOR to fixings

---------

Co-authored-by: deeleeramone <>

* fix for plotly 7 breaking change to schemas

* [V5] `openbb-tmx`: Refactor extension for V5 (#7668)

* refactor tmx provider for v5

* fix tests..

* fix tests stack trace exposure

* fix workflow setup

* [V5] `openbb-nasdaq`: Refactor provider for V5. (#7670)

* refactor nasdaq provider for v5

* add workflows

* ty fix

* [V5] `openbb-fred`: Refactor as V5 extension. (#7669)

* refactor fred extension for v5

* fix markdown MD037 lint error in README

* codespell

* [V5] `openbb-cboe`: Refactor for V5 + Add Payoff Diagrams (#7617)

* refactor cboe for v5

* use zoneinfo instead

* fix test

* some fixes related to the cache access

* fix a couple of tests

* fix the test coverage

* [V5] `openbb-deribit`: Refactor provider for V5 (#7674)

* refactor openbb-deribit for v5

* restructure the optimizer around the published combos data and add integration test suites

* fix markdown lint errors

* remove openbb-econdb provider (#7675)

* codespell

* [V5] `openbb-sec`: Refactor for V5 (#7525)

* refactor openbb-sec for v5

* linting

* ty

* normalize compare_company_facts

* add workflows

* python 3.10 fix

* add more thorough url validation and tests

* ty check

* ty for python 3.10

* reconfigure with apps

* temp pyproject overrride

* pyproject

* pyproject

* pyproject

* codespell

* pyproject

* fix uk schema file links in schema_files

* test coverage

* test_cli

* port #7547 into this pr

* no hard coded prefix

* improve filing rendering capabilities

* fix xml text detection

* make codeql happy

* missed a file in the commit

* test coverage

* codespell

* fix flakey test

* some updates

* management_ownership --> management_profiles

* proxy statement markdown

* ruff

* fix test coverage

* more tests

* test coverage

* fix lint errors

* Add SEC adviser search, profile, and universe routes (#7559)

* Add SEC institutional data fetchers

* Add SEC filing index and Form D routes

* Add SEC investment adviser people data

* Expose SEC adviser and institutional routes

* fix(sec): address adviser review feedback

* refactor(sec): narrow adviser support to IAPD search

* feat(sec): add adviser firm and individual searches

* feat(sec): add adviser profile drill-down

* fix: repair pre-commit configuration

* feat(sec): add adviser universe route

* feat(sec): expose complete Form ADV data

---------

Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com>

* fix test coverage

---------

Co-authored-by: deeleeramone <>
Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>

* [V5] `openbb-finra`:  Refactor for V5 (#7676)

* refactor finra provider for v5

* add workflows

* fix tests

* fix lint errors

* [V5] Update Repository License to Apache 2.0 (#7677)

* change license to Apache 2.0 for V5

* codespell

* bump devtools and repoint pyproject.toml

* Enterprise Flask Migration Toolkit (#7264)

* feat: Add Flask-to-OpenBB enterprise migration toolkit

- Implement Router.from_flask() for zero-touch legacy API conversion
- Enable 4-hour migration vs 6-month traditional rewrite (80% cost reduction)
- Generate FastAPI endpoints from Flask routes with automatic type validation
- Support enterprise consulting services and custom integration workflows

Demonstrates OpenBB's competitive advantage for institutional client migrations.
Complements existing Workspace applications like Open Portfolio suite.

* chore: Resolve .gitignore conflict and add common ignores

* refactor: implement Phase 1 Flask integration architecture- Move Flask conversion logic to openbb_core.app.utils.flask- Add Flask detection to extension_loader - Integrate with OpenBB's core extension system- Add Flask dependency validation with sys.modules checkingAddresses @deeleeramone's architectural feedback for native OpenBB integration.

* docs: add Flask direct entry point demos- demo_direct_flask_entry_point.py: shows direct Flask instance reference- example_pyproject_flask_entry.toml: demonstrates pyproject.toml configurationSupports new architecture eliminating wrapper extensions.

* Implement Phase 1 Flask adapter per code review feedback

- Minimal working implementation with Flask detection and router creation
- Removes complex code generation logic for focused Phase 1 delivery
- Establishes foundation for Phase 2 route conversion features

* Fix Flask integration: Replace missing FlaskToOpenBBAdapter with WSGIMiddleware

- Remove FlaskToOpenBBAdapter which was not implemented
- Use FastAPI's WSGIMiddleware to mount Flask apps directly
- Update extension_loader to use returned Router object
- Convert utils.py to utils/__init__.py to support flask submodule
- Addresses PR review comment about unhandled AttributeError

* Address PR review feedback: fix Flask imports and remove unused files

- Revert .gitignore to upstream/develop
- Remove AI-generated demo/example files and flask_adapter extension
- Move Flask/werkzeug imports inside conditional blocks to avoid ImportError
- Use lazy imports via __getattr__ in utils/flask/__init__.py
- Add Flask tests with @pytest.mark.skipif markers

* Force APIRouter.include_router to propagate Mount paths instead of dropping them. (#1)

This change ensures that mounted ASGI applications (such as Flask apps wrapped in WSGIMiddleware) are not dropped when `APIRouter.include_router` is called.

Previously, while the initial load in `ExtensionLoader` worked as expected, the `Mount` objects were ignored by FastAPI's default inclusion logic. This caused the mounted elements to be lost during the final application assembly, resulting in 404 errors for the Flask routes.

This fix overrides the inclusion logic to manually propagate `Mount` objects downstream.

* feat(flask): Add metadata layer for OpenAPI documentation

Enhance Flask-to-OpenBB converter with structured docstring parsing:
- Parse Google-style docstrings (summary, description, params)
- Extract parameter descriptions from Args section
- Pass metadata to Router.command() for rich OpenAPI docs

This addresses PR feedback to provide tangible benefit by generating
comprehensive API documentation for migrated Flask routes.

* feat(flask): Implement manual OpenAPI spec generation and attachment

- Add FlaskParam and FlaskRouteInfo TypedDict for type-safe metadata
- Implement OpenAPISpecGenerator for Flask→OpenAPI conversion
- Extract route metadata via FlaskIntrospector
- Attach generated spec to router.openbb_openapi_spec_ext
- Add unit tests (3/3 passing)

Addresses WSGI/mount boundary issue where Router.command metadata
cannot propagate through WSGIMiddleware. Spec attached to router
instance for downstream OpenAPI assembly.

Resolves maintainer feedback on PR #7264

* feat(flask): Implement FlaskMountRegistry for multiple mount support

- Add FlaskMountRegistry class for centralized OpenAPI spec management
- Replace router.openbb_openapi_spec_ext with registry pattern
- Support multiple Flask apps at different mount prefixes
- Automatic path rewriting in aggregated OpenAPI specs
- Add registry test case (4/4 tests passing)

Addresses @deeleeramone's feedback on PR #7264 regarding router
attribute fragility and multiple mount support. Registry provides
lifecycle-independent state management and enables enterprise
scenarios with multiple Flask apps.

Resolves: OpenBB-finance/OpenBB#7264 (partial)

* feat(core): load Flask apps as openbb_core_extension WSGI sub-apps

A Flask app referenced directly by an openbb_core_extension entry point is
mounted via WSGIMiddleware and its routes are introspected into openapi.json
(operationId/widgetId/mcp_tool, parameters, request bodies, security, widget_config
and HTML widgets) so the widget factory and MCP server can discover them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(core): 100% coverage for flask utils + flask dev dependency

Add branch-coverage tests for the Flask integration package (introspection,
AST analysis, docstrings, OpenAPI generation, registry, loader, detection) and
declare flask as a dev dependency so the suite runs in CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(flask): treat f-string returns as HTML responses

* fix(flask): mount via a2wsgi instead of deprecated starlette WSGIMiddleware

- add openbb-core[flask] extra (flask, a2wsgi); a2wsgi resolved through require_optional
- run the WSGI serve test through mount_flask_extensions; drop httpx importorskip
- core CI installs [pandas,flask] and httpx2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(flask): cover failed entry point loads; narrow optional types for ty

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com>
Co-authored-by: deeleeramone <>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* perf(core): vectorize the date conversion in `basemodel_to_df` (#7622)

* perf(core): vectorize the date conversion in basemodel_to_df

basemodel_to_df ran three per-element Python passes over the date column of
every payload it converted. Series.apply(to_datetime) calls pandas.to_datetime
once per row, and because each call receives a lone scalar with no format hint,
pandas also re-runs its datetime format guesser on every row.

Parse the column in one call instead, and use vectorized comparisons for the
all-midnight test and the reduction to datetime.date.

The element-wise parse is kept as a fallback for one case that the vectorized
path cannot represent: a column mixing UTC offsets, such as a series crossing a
daylight-savings boundary. Parsing per element lets each value keep its own
offset and yields an object column of tz-aware Timestamps, whereas a single
to_datetime call over that column raises "Mixed timezones detected". That
behaviour is covered by test_to_df_daylight_savings and is preserved exactly.

Measured on a payload built through EquityHistoricalData, median of 9 under an
exclusive CPU lock:

  250 daily bars     8.92 ms -> 1.46 ms
  1,000 daily bars  32.93 ms -> 3.13 ms
  5,000 daily bars 162.25 ms -> 12.23 ms

* fix a broken test - unrelated to this PR...

---------

Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com>
Co-authored-by: deeleeramone <>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix lint errors

* fix oecd lint error

* [V5] `openbb-mcp-server`: Refactor for v5 - Spec, Config, Packaging, Test Coverage (#7495)

* stash some changes

* add more robust testing

* mypy

* point PR at V5

* introduce spec file

* codespell

* test fix

* fix workflow environment setup

* fix workflow environment setup

* fix workflow environment setup

* add pyyaml to dependencies

* split lint jobs

* fix workflow environment setup

* fix workflow environment setup

* workflow env setup

* workflow env setup

* clean up code comments

* add auth hook entrypoints

* codespell

* add codegen feature

* codespell

* move _unpack into dispatchers for consistency with codegen packages

* surface nested models in the response

* fix missing coverage in CI

* socrata updates

* test fix

* detect plotly output

* add --include and --exclude flags from generate-extension command

* refactor mcp server for v5

* test action

* fix tests

* tests

* test fixture name

* revert: drop unrelated provider/README changes from mcp-server refactor

Strip the changes to ``README.md`` and ``openbb_platform/providers/{imf,
tradingeconomics,yfinance}`` that snuck into 4ac3602 (refactor mcp server
for v5). Those files are out of scope for the mcp-server work and were
modified inadvertently — restore them to their pre-4ac3602 state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* tests and workflows

* fix workflow

* tests and workflows

* tests and workflows

* tests and workflows

* tests and workflows

* beartype shim for 3.15

* muck around with beartype for 3.15

* muck around with beartype for 3.15

* no 3.15 runners for mcp-server

* update skill files

* cap test matrix at python 3.14

* merge branch v5

* no useless comments

* platform controller command description split

* merge URL overloads from path params

* exclude none and unset from model dump

* refactor for fastmcp4

* wrap markdown lines that are too long

---------

Co-authored-by: deeleeramone <>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* update pre-commit, noxfile, and uv locks

* fixes for docstring generation

* test coverage

* fix cli renderer helper with figure object JSON

* fix the figure font when rendered

* refactor cookiecutter

* bump cookiecutter packagge version

* fix sec test by adding fixture

* fix desktop environments test

* fix(cli): inherit path-item-level OpenAPI parameters (#7606)

* fix(cli): inherit path-item-level OpenAPI parameters

OpenAPI 3.x lets a Path Item Object declare `parameters` shared by every
operation under that path, with operation-level entries overriding them by
(name, in). The codegen read only `op.get("parameters")`, so inherited
parameters were dropped silently — the generated command kept the URL
template but had nothing registered to fill it.

Real-world impact: the Xero Accounting API declares its required
`xero-tenant-id` header once per path item across all 138 paths. Before this
change `build_command_spec` produced 78 commands and none carried the
header, so every generated command 403s. Nothing warned.

Adds `operation_parameters()`, which merges the two levels and dereferences
both, and routes the pre-computed spec path (`build_command_spec`) and the
interactive path (`build_command_index` -> `build_parser_from_operation`)
through it. Unresolvable refs, non-dict entries, and nameless parameters are
skipped as before. Specs without path-item parameters are unaffected.

* fix(cli): narrow path-item inheritance to path and query parameters

Per review: headers do not translate into a Python interface function, and
outbound headers are transport configuration
(SystemSettings.PythonSettings.http.headers, the CLI's -H) or a security-scheme
concern — not a per-command argument.

Path-item `in: header` and `in: cookie` entries are now dropped rather than
inherited. Operation-level parameters are untouched, so an operation that
declares its own header keeps today's behavior.

Scope is now only what cannot be supplied any other way: `in: path` and
`in: query` parameters declared on the Path Item Object.

* fix(cli): merge allOf compositions in response schemas

Response-schema $refs were already expanded by deref_schema, but a schema
whose top level is an allOf composition was left unflattened. The properties
live inside the members, so a consumer reading them off the composition finds
none. fetcher_gen._data_schema looks for `properties.results`, gets nothing,
and falls through to _unwrap_schema_envelopes, which handles oneOf and anyOf
but not allOf. The generated Data model ends up with no fields.

Codat's listBills response is `allOf: [{properties: {results}}, {properties:
{_links, pageNumber, pageSize, totalResults}}]`, which produced an empty model.

merge_allof collapses a composition of object subschemas into one object
schema: properties unioned with the first declaration winning on conflict,
required unioned, and sibling keywords on the allOf node outranking members.
A composition that is not a plain intersection of object subschemas (a member
carrying its own oneOf/anyOf, or a non-object type) is returned unchanged
rather than flattened into something the spec does not describe. Nested
compositions are merged too, so a $ref inside a merged member still resolves.

Applied to extract_response_schema and extract_response_schemas.

Measured across five specs that use the pattern, counting operations whose
response schema exposes readable properties: 244 of 588 before, 394 after
(Codat Accounting 36 to 88, Codat Banking 0 to 8, Codat Commerce 1 to 11,
Rebilly 62 to 104, Box 145 to 183).

* fix(cli): merge allOf compositions in request body schemas

Same gap as the response side. request_body_parameters needs `type: object`
or `properties` to flatten a body into parameters, and an allOf composition
carries neither, so a POST or PUT generated from one gets no body parameters
at all.

extract_request_body_schema now runs merge_allof after deref_schema, matching
extract_response_schema.

Across the same five specs, counting request bodies that produce parameters:
138 of 206 before, 177 after (Codat Accounting 1 to 26 of its 30 bodies,
Rebilly 50 to 63, Box 87 to 88).

* fix(cli): stop annotation keywords blocking an allOf merge

_mergeable_allof_members required every member's keys to come from a small
whitelist, so any unrecognized keyword disqualified the whole composition.
Codat's PagingInfo carries `definitions` next to its properties, which meant
the live Codat-Accounting.yaml never merged and its response models stayed
empty. The APIs.guru copy of the same API omits that key, which is why the
earlier measurements looked clean.

The check is now a blocklist. A member blocks the merge when it carries its
own combinator (oneOf/anyOf/allOf/not), an unresolved $ref left by a cycle,
a scalar or array constraint (enum/const/items), or a type other than object.
Annotation keywords that do not affect the intersection (title, description,
examples, definitions, additionalProperties, vendor x- keys) no longer block
it, and are dropped from the merged result along with the members.

On the live Codat spec, operations whose response schema exposes readable
properties go from 36 of 127 to 114. Across the five specs measured earlier:
244 of 588 before, 488 after (was 394 under the whitelist).

Corpus check over 2,816 response and request-body extractions in 6 specs:
567 changed, every one attributable to an allOf in the pre-merge output,
0 unexplained. Twilio declares no allOf compositions and is unchanged.

* fix(cli): emit a name once when it is both a parameter and a body property

_signature_params appended request-body properties and then operation
parameters without deduplicating, so a name declared in both places produced
two function parameters with the same name and the generated module raised
SyntaxError.

Codat's push endpoints hit this: /push/bankAccounts/{accountId}/bankTransactions
declares accountId as a path parameter and repeats it in the request body, so
connections.push.bankAccounts.bankTransactions generated `accountId: str` and
`accountId: str = None` in one signature.

The operation parameter wins, since it carries the path placeholder and its own
required flag. The request payload is unchanged: _render_body_block derives body
fields from request_body_schema rather than from this list, so accountId is
still sent in the body.

This predates the path-item and allOf work in this PR. On origin/v5 the same
spec produces the same duplicate; on this branch the Codat spec generates 91
commands with 0 duplicated signatures, down from 1.

* fix(cli): use the safe identifier for keyword-named body properties

_render_body_block already writes `{'from': from_}`, keying the payload by the
wire name and reading a safe identifier, but _signature_params declared the raw
name. A body property named after a Python keyword therefore emitted
`from: str = None` and the generated module raised SyntaxError.

This did not fire before the allOf work in this PR, because a composed request
body produced no body parameters at all. Codat's Transfer body is such a
composition and has a `from` property, so connections.push.transfers started
generating invalid syntax once the body flattened.

_signature_params now emits safe_field_name(name)[0], the same helper
fetcher_gen and pydantic_gen already use. The body/query split in
_render_body_block compares against the safe names too: it previously matched
signature names against wire names, so `from_` was not recognized as a body
field and leaked into the query string as a `from_` parameter.

End to end on Codat-Accounting.yaml, generating the full extension and byte
compiling every emitted module: 136 files, 0 failures. origin/v5 emits 1 file
that does not compile (duplicate argument 'accountId').

Known gap left alone: an operation parameter named after a keyword would still
break, since the query and path lines use the raw name as a local variable.
None of the five specs checked declares one.

* fix(cli): do not treat instance data as schema, and sanitize POST identifiers

Two defects found by generating extensions from real specs and byte compiling
every emitted module.

merge_allof and deref_schema walked every value in a schema dict, including
keywords that hold instance data rather than subschemas. A `default` of
`{"allOf": [{"a": 1}, {"b": 2}]}` was rewritten to `{"type": "object"}`, and a
`$ref` key inside an example was resolved as if it were a reference. Both now
copy `default`, `example`, `examples`, `enum`, `const` and vendor `x-` values
through untouched.

_signature_params emitted operation parameter names verbatim, so a wire name
that is not a Python identifier produced invalid syntax. Rebilly declares an
`Organization-Id` header and a `REB-APIKEY` security header, which emitted
`REB-APIKEY: str = None`. It now uses safe_field_name, matching fetcher_gen,
and _render_body_block keys the query dict by the wire name while reading the
safe identifier so the request is unchanged.

This surfaced through the allOf work rather than being caused by it: a composed
request body used to yield no properties, so `has_body` was false in
package_gen and the command was generated as a GET fetcher, where identifiers
were already sanitized. With bodies flattening, 14 of Codat's 24 POST endpoints
correctly move to the POST path, which had never been exercised by these specs.

Generating the full extension and compiling every module:

  Codat-Accounting.yaml   v5: 1 failure    branch: 0   (136 files)
  Rebilly 2.1             v5: 14 failures  branch: 1   (97 files)

The one remaining Rebilly failure is `async def 3dsecure(` in the router, which
fails identically on v5. Sanitizing that is a naming decision about the command
surface, so it is left alone here.

Known gap: a non-credential header parameter is still placed in the query
string on the POST path. Pre-existing, and unchanged by this PR.

* fix(cli): resolve signature collisions on the emitted identifier

The previous dedupe compared wire names, but the failure it prevents depends on
the sanitized identifier. Two wire names can collapse onto one (`from` and
`from_`, `Organization-Id` and `Organization_Id`), and operation_parameters
keeps a name declared twice under different `in` locations by design, so both
cases could still emit a duplicate argument.

_signature_params now tracks the identifiers it has emitted and skips anything
that would repeat one. Emission order is unchanged, so existing signatures are
byte-identical; only genuinely colliding names are dropped, and operation
parameters still win over body properties.

Neither collision occurs in Codat-Accounting.yaml or Rebilly 2.1. This closes
the class rather than the instance, since the instances are what this PR has
been finding.

Generation unchanged: Codat 136 files 0 failures, Rebilly 97 files 1 failure
(`async def 3dsecure(`, identical on v5).

* test(cli): cover the instance-data guard, and drop a redundant branch

Mutation checking the new tests (revert each fix, confirm its test fails)
found two problems with the previous commits.

The guard that stops merge_allof and deref_schema from walking into `default`,
`example`, `enum`, `const` and vendor values shipped with no test at all. It is
now covered from both directions: a default holding an `allOf` key keeps its
value, and a `$ref` inside a default stays a literal while a real reference
beside it still resolves.

The body-property loop also carried a redundant check. It tested the raw wire
name against the operation parameter names before testing the sanitized one,
but `operation_param_names` holds both forms and `safe_field_name` is idempotent
on identifiers, so the first test could never fire alone. Reverting it left
every test passing, which is what surfaced it. Removed, and the sanitized name
is now computed once.

All nine mutations are caught by the suite: both data guards, the allOf
blocklist in each direction, the response merge wiring, body/parameter
precedence, the keyword identifier, the body/query split and the
emitted-identifier dedupe.

cli/tests at 1,954 passed against the same 80 environment failures as the base.
Generation unchanged: Codat 136 files 0 failures, Rebilly 97 files 1 failure.

* fix(cli): route required path-item headers/cookies through credential handling

* fix(cli): narrow Popen.stdin/stdout for ty in run_in_obb fixture

---------

Co-authored-by: deeleeramone <>

* fix warnings raised by federal_reserve on some xlsx workbook parsing

* fix publish workflows

* test publish pipeline with openbb-core-v2.0.0rc0 (#7681)

* fix publish workflows with missing tag job, some tests and bump fastapi

* fix python 3.10 test failure in core

* actually fix python 3.10 test failure in core

* deincrement openbb-core version to allow release pattern

* bump core version (#7682)

* remove uv.sources from pyproject.toml files and point to openbb-core-2.0.0 on PyPI

* remove oecd cache asset that wasn't supposed to be commuitted

* remove poetry.lock, update pyproject.tml and uv.lock for openbb-platform-api-v2.0.0 (#7684)

Co-authored-by: deeleeramone <>

* add the missing publish-openbb-platform-api.yml workflow file

* remove poetry.lock, update pyproject.tml and uv.lock for openbb-platform-api-v2.0.0 (#7685)

Co-authored-by: deeleeramone <>

* fix the tag generation after publish

* [Release] `openbb-charting-v4.0.0` (#7686)

* up openbb-charting to 4.0.0 and fill missing test coverage in chart_style

* test coverage and format markdown files

---------

Co-authored-by: deeleeramone <>

* remove scikit-learn from dependencies, update tests, and format markdown files (#7687)

Co-authored-by: deeleeramone <>

* [Release] `openbb-cli-v2.0.0` (#7692)

* fix missing test coverage in openbb_cli

* fix conftest

---------

Co-authored-by: deeleeramone <>

* add missing publish-openbb-cli.yml workflow

* [Release] `openbb-cli-v2.0.0` (#7693)

* fix missing test coverage in openbb_cli

* fix conftest

---------

Co-authored-by: deeleeramone <>

* test fixes for cli...

* [Release] `openbb-cli-v.2.0.0` (#7694)

* fix missing test coverage in openbb_cli

* fix conftest

---------

Co-authored-by: deeleeramone <>

* fix hanging mcp server test

* [Release] `openbb-mcp-server-v2.0.0` (#7695)

Co-authored-by: deeleeramone <>

* update uv.lock (#7696)

Co-authored-by: deeleeramone <>

* release openbb-commodity-v2.0.0 (#7697)

Co-authored-by: deeleeramone <>

* update uv.lock (#7698)

Co-authored-by: deeleeramone <>

* update uv.lock (#7699)

Co-authored-by: deeleeramone <>

* update uv.lock (#7700)

Co-authored-by: deeleeramone <>

* [Release] `openbb-econometrics-v2.0.0` (#7701)

* update uv.lock

* update pyproject.toml

---------

Co-authored-by: deeleeramone <>

* update uv.lock (#7703)

Co-authored-by: deeleeramone <>

* update uv.lock (#7702)

Co-authored-by: deeleeramone <>

* update uv.lock (#7704)

Co-authored-by: deeleeramone <>

* update uv.lock (#7705)

Co-authored-by: deeleeramone <>

* update uv.lock (#7706)

Co-authored-by: deeleeramone <>

* [V5] Fix a Number of V5 Bugs (#7707)

* fix a number of v5 bugs

* fix lint error

* more lint

* fixes for quantitative, technical, charting, famafrench for version bumps

---------

Co-authored-by: deeleeramone <>

* update uv.lock (#7709)

Co-authored-by: deeleeramone <>

* update uv.lock (#7708)

Co-authored-by: deeleeramone <>

* update uv.lock (#7710)

Co-authored-by: deeleeramone <>

* update uv.lock (#7711)

Co-authored-by: deeleeramone <>

* [Release] `openbb-cboe-v2.0.0` (#7713)

Co-authored-by: deeleeramone <>

* update uv.lock (#7714)

Co-authored-by: deeleeramone <>

* update uv.lock (#7717)

Co-authored-by: deeleeramone <>

* [Release] `openbb-ecb-v2.0.0` (#7715)

* update uv.lock

* update uv.lock

---------

Co-authored-by: deeleeramone <>

* update uv.lock (#7718)

Co-authored-by: deeleeramone <>

* update uv.lock (#7719)

Co-authored-by: deeleeramone <>

* update uv.lock (#7720)

Co-authored-by: deeleeramone <>

* add missing publish-openbb-fred.yml to repo

* update uv.lock (#7723)

Co-authored-by: deeleeramone <>

* update uv.lock (#7722)

Co-authored-by: deeleeramone <>

* update uv.lock (#7716)

Co-authored-by: deeleeramone <>

* update uv.lock (#7724)

Co-authored-by: deeleeramone <>

* update uv.lock (#7726)

Co-authored-by: deeleeramone <>

* [Release] `openbb-fred-v2.0.0` (#7725)

* update uv.lock

* fix tests and dependencies

* fix test_fred_fetchers

---------

Co-authored-by: deeleeramone <>

* [Release] `openbb-imf-v3.0.0` (#7727)

* update uv.lock

* fix tests and dependencies

* fix test_fred_fetchers

* bump openbb-imf version to 3.0.0

---------

Co-authored-by: deeleeramone <>

* update uv.lock (#7729)

Co-authored-by: deeleeramone <>

* update uv.lock (#7728)

Co-authored-by: deeleeramone <>

* update uv.lock (#7730)

Co-authored-by: deeleeramone <>

* update uv.lock (#7731)

Co-authored-by: deeleeramone <>

* update uv.lock (#7732)

Co-authored-by: deeleeramone <>

* update uv.lock (#7733)

Co-authored-by: deeleeramone <>

* cookiecutter pyproject and lock

* update pyproject.toml (#7734)

Co-authored-by: deeleeramone <>

* update pyproject.toml (#7735)

Co-authored-by: deeleeramone <>

* update uv.lock (#7736)

Co-authored-by: deeleeramone <>

* fix some sec issues, allegedly (#7737)

Co-authored-by: deeleeramone <>

* update uv.lock (#7738)

Co-authored-by: deeleeramone <>

* update main pyproject.toml

* lint fixes

* update assets (#7739)

Co-authored-by: deeleeramone <>

* [Release] `openbb-v5.0.0` (#7740)

* update assets

* add missing workflow

---------

Co-authored-by: deeleeramone <>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: deeleeramone <>
Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>
Co-authored-by: Dex <i@dex.moe>
Co-authored-by: Monte Hoover <monte.b.hoover@gmail.com>
Co-authored-by: Boris Li <65254053+BorisQuanLi@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Lucas Zimmermann <lucaszmayer@gmail.com>
2026-09-29 14:45:53 +00:00

38 KiB
Vendored
Raw Permalink Blame History

OpenBB MCP Server

This extension enables LLM agents to interact with OpenBB Platform's REST API endpoints through the MCP protocol.

With tool discovery enabled, the server hides the full tool catalog behind a few discovery tools, so agents search for and call only the tools they need. This keeps the initial tool list small — preventing token bloat — while still giving agents access to the full platform on demand.

Discovery is stateless: every client sees the same tool list, and hidden tools are called through call_tool or directly by name, so multiple agents can share one server.

Installation & Usage

pip install openbb-mcp-server

The server exposes the routes of the installed OpenBB extensions, so install the data extensions too, either all of them (pip install openbb) or the ones you need (pip install openbb-equity openbb-yfinance). Install the cli extra (pip install "openbb-mcp-server[cli]") for the openbb-cli dispatcher tools.

Start the OpenBB MCP server with default settings:

openbb-mcp

Or use the uvx command:

uvx --from openbb-mcp-server --with openbb openbb-mcp

Command Line Options

Enter openbb-mcp --help to see the docstring from the command line.

--help
    Show this help message and exit.

--app <app_path>
    The path to the FastAPI app instance. This can be in the format
    'module.path:app_instance' or a file path 'path/to/app.py'.
    If not provided, the server will run with the default built-in app.

--name <name>
    The name of the FastAPI app instance or factory function in the app file.
    Defaults to 'app'.

--factory
    If set, the app is treated as a factory function that will be called
    to create the FastAPI app instance.

--spec <path>
    Path to an `openbb-cli` generated `.spec` file. Serves a proxy app whose
    routes forward to the spec's `base_url`. Mutually exclusive with --app.

--config-file <path>
    Path to a TOML config file, the highest-priority layer of the
    `openbb.toml` cascade. Also read from $OPENBB_MCP_CONFIG,
    $OPENBB_API_CONFIG, or $OPENBB_CONFIG.

--host <host>
    The host to bind the server to. Defaults to '127.0.0.1'.
    This is a uvicorn argument.

--port <port>
    The port to bind the server to. Defaults to 8001.
    This is a uvicorn argument.

--transport <transport>
    The transport mechanism to use for the MCP server.
    Defaults to 'streamable-http'.

--allowed-categories <categories>
    A comma-separated list of tool categories to serve. Tools in other
    categories are not listed, searchable, or callable.
    If not provided, all categories are served.

--default-categories <categories>
    A comma-separated list of tool categories to list when tool discovery is off.
    Tools in other categories are not served. Defaults to 'all'.

--tool-discovery
    If set, the tools are hidden behind available_categories, available_tools, search_tools, and call_tool.

--system-prompt <path>
    Path to a TXT file with the system prompt.

--server-prompts <path>
    Path to a JSON file with a list of server prompts.

Other arguments

Every other --key value is routed by name:

  • An MCPSettings field sets that setting, e.g. --enable-cli-tools false or --server-auth '["user", "pass"]'.
  • --httpx-<option> sets an option of the httpx client that calls the API, e.g. --httpx-verify false.
  • Anything else is passed to uvicorn, e.g. --log-level debug or --ssl-keyfile key.pem.

Configuration

The server can be configured through multiple methods, with settings applied in the following order of precedence:

  1. Command Line Arguments: Highest priority, overriding all other methods.
  2. [mcp] table of openbb.toml: Defaults for any command line argument, read from the layered openbb.toml cascade (see openbb.toml). They are applied like command line arguments, so they override environment variables.
  3. Environment Variables: Each setting can be controlled by an OPENBB_MCP_* environment variable, which will override the configuration file.
  4. Configuration File: A JSON file at ~/.openbb_platform/mcp_settings.json provides the base configuration. If the configuration file does not exist, one will be populated with the defaults.

Note: For some data providers you need to set your API key in the ~/.openbb_platform/user_settings.json file.

Authentication

The MCP server supports client-side and server-side authentication to secure your endpoints.

Server-Side Authentication

Server-side authentication requires incoming HTTP requests to provide credentials. This is configured using the server_auth setting, which accepts a (username, password) pair.

When server_auth is set, clients must include an Authorization header with a Bearer token. The token is the Base64 encoding of username:password, and requests without it receive 401 Unauthorized.

Example: Environment Variable

OPENBB_MCP_SERVER_AUTH='["myuser", "mypass"]'

Example: mcp_settings.json

{
  "server_auth": ["myuser", "mypass"]
}

Client-Side Authentication

Client-side authentication configures the MCP server to send credentials, as HTTPX auth, on its requests to the wrapped API.

Example: Environment Variable

OPENBB_MCP_CLIENT_AUTH='["client_user", "client_pass"]'

Example: mcp_settings.json

{
  "client_auth": ["client_user", "client_pass"]
}

Programmatic Authentication

The auth parameter of create_mcp_server accepts any FastMCP AuthProvider, a (username, password) pair (the same scheme as server_auth), or None. Anything else raises TypeError.

from fastapi import FastAPI
from fastmcp.server.auth.providers.jwt import JWTVerifier
from openbb_mcp_server.app.app import create_mcp_server
from openbb_mcp_server.models.settings import MCPSettings

auth = JWTVerifier(
    jwks_uri="https://auth.example.com/.well-known/jwks.json",
    issuer="https://auth.example.com",
    audience="openbb-mcp",
)
mcp_server = create_mcp_server(MCPSettings(), FastAPI(), auth=auth)

Advanced Configuration: Lists and Dictionaries

For settings that accept a list or a dictionary, you have two flexible formats for defining them in both command-line arguments and environment variables.

1. Comma-Separated Strings

This is a simple and readable way to define lists and simple dictionaries.

  • Lists: Provide a string of comma-separated values.
    • Example: equity,news,crypto
  • Dictionaries: Provide a string of comma-separated key:value pairs.
    • Example: host:0.0.0.0,port:9000

2. JSON-Encoded Strings

For more complex data structures, or to ensure precise type handling (e.g., for numbers and booleans), you can use a JSON-encoded string.

  • Lists: A standard JSON array.
    • Example: '["equity", "news", "crypto"]'
  • Dictionaries: A standard JSON object.
    • Example: '{"host": "0.0.0.0", "port": 9000}'

Important Note on Quoting: When passing JSON-encoded strings on the command line, it is highly recommended to wrap the entire string in single quotes ('). This prevents your shell from interpreting the double quotes (") inside the JSON string, which can lead to parsing errors.

Practical Examples

Here’s how you can apply these formats in practice:

Command-Line Arguments:

# List with comma-separated values
openbb-mcp --default-categories equity,news

# List with a JSON-encoded string (note the single quotes)
openbb-mcp --default-categories '["equity", "news"]'

# Dictionary with comma-separated key:value pairs
openbb-mcp --uvicorn-config "host:0.0.0.0,port:9000"

# Dictionary with a JSON-encoded string (note the single quotes)
openbb-mcp --uvicorn-config '{"host": "0.0.0.0", "port": 9000, "env_file": "./path_to/.env"}'

Environment Variables (in a .env file):

# List with comma-separated values
OPENBB_MCP_DEFAULT_TOOL_CATEGORIES="equity,news"

# List with a JSON-encoded string
OPENBB_MCP_DEFAULT_TOOL_CATEGORIES='["equity", "news"]'

# Dictionary with comma-separated key:value pairs
OPENBB_MCP_UVICORN_CONFIG="host:0.0.0.0,port:9000"

# Dictionary with a JSON-encoded string
OPENBB_MCP_UVICORN_CONFIG='{"host": "0.0.0.0", "port": 9000, "env_file": "./path_to/.env"}'

openbb.toml

The launcher reads the same layered TOML cascade as openbb-core, each layer overriding the one before: the [tool.openbb] table of the nearest pyproject.toml (so [tool.openbb.mcp] there), then ~/.openbb_platform/openbb.toml, then the nearest openbb.toml walking up from the working directory, then the file passed with --config-file (or $OPENBB_MCP_CONFIG, $OPENBB_API_CONFIG, $OPENBB_CONFIG). .openbb.toml works in place of openbb.toml.

[mcp]
host = "0.0.0.0"
port = 8005
default-categories = "equity,economy"
tool-discovery = true

[mcp.auth]
hooks = ["my_pkg.auth:bearer_token_check"]

[mcp.middleware]
hooks = ["my_pkg.middleware:request_logger"]

[env]
OPENBB_MCP_NAME = "Research MCP"
  • [mcp] sets defaults for the command line arguments.
  • [mcp.auth] and [mcp.middleware] list module:attr entry points of async def hook(request, call_next) functions. They wrap the HTTP and SSE transports, not stdio; auth hooks run before middleware hooks.
  • [env] sets environment variables before the server starts, without replacing variables already set in the shell. Values support $VAR / ${VAR} substitution.
  • [mcp.spec] serves an openbb-cli generated .spec file as a proxy to its upstream server instead of the installed extensions, the same as --spec. [mcp.spec.NAME] subtables mount several specs, each with its own headers and hooks.

The configure_mcp_server skill covers every table and the spec proxy mode in detail.

Settings Reference

All settings in the MCPSettings model can be configured via the mcp_settings.json file or as environment variables.

Setting Environment Variable Type Default Description
api_prefix OPENBB_MCP_API_PREFIX string None Overrides the API prefix from SystemService.
name OPENBB_MCP_NAME string "OpenBB MCP" Server name.
description OPENBB_MCP_DESCRIPTION string Server description.
version OPENBB_MCP_VERSION string None Server version.
instructions OPENBB_MCP_INSTRUCTIONS string None Server instructions sent during the MCP initialize handshake. Auto-populated from system prompt if not set.
default_tool_categories OPENBB_MCP_DEFAULT_TOOL_CATEGORIES list[string] ["all"] With tool discovery off, the categories served; other tools are not listed or callable, even through run_pipeline, unless a route sets enable: true. Ignored with tool discovery on.
allowed_tool_categories OPENBB_MCP_ALLOWED_TOOL_CATEGORIES list[string] None The only categories served, with or without tool discovery; other routes are never registered. None or ["all"] serves every category.
enable_tool_discovery OPENBB_MCP_ENABLE_TOOL_DISCOVERY boolean False Hide the tools behind available_categories, available_tools, search_tools, and call_tool.
list_page_size OPENBB_MCP_LIST_PAGE_SIZE integer None Max items per page in MCP list responses. None disables pagination.
describe_responses OPENBB_MCP_DESCRIBE_RESPONSES boolean False Include response types in tool descriptions.
system_prompt_file OPENBB_MCP_SYSTEM_PROMPT_FILE string None Path to a text file for the system prompt.
server_prompts_file OPENBB_MCP_SERVER_PROMPTS_FILE string None Path to a JSON file with a list of server prompt definitions.
default_skills_dir OPENBB_MCP_DEFAULT_SKILLS_DIR string (bundled skills dir) Directory of bundled skills, one sub-directory per skill with a SKILL.md. Set to null or an empty string to disable.
skills_reload OPENBB_MCP_SKILLS_RELOAD boolean False Reload skill files on every read (useful during development).
skills_providers OPENBB_MCP_SKILLS_PROVIDERS list[string] None Vendor skill provider short-names to load (e.g. ["claude", "cursor"]).
on_duplicate OPENBB_MCP_ON_DUPLICATE string None Behavior when a tool, resource, or prompt is registered twice (warn, error, replace, ignore).
mask_error_details OPENBB_MCP_MASK_ERROR_DETAILS boolean None Mask error details from user functions.
enable_cli_tools OPENBB_MCP_ENABLE_CLI_TOOLS boolean True Register the openbb-cli dispatcher tools when openbb-cli is installed.
module_exclusion_map OPENBB_MCP_MODULE_EXCLUSION_MAP dict[str, str] None Route path segments mapped to Python modules; routes under a segment are hidden while its module is imported. None uses {"coverage": "openbb_core"}, and {} hides nothing.
uvicorn_config OPENBB_MCP_UVICORN_CONFIG dict {"host": "127.0.0.1", "port": "8001"} Configuration for the Uvicorn server.
httpx_client_kwargs OPENBB_MCP_HTTPX_CLIENT_KWARGS dict {} Configuration for the async httpx client.
client_auth OPENBB_MCP_CLIENT_AUTH tuple[string, string] None (username, password) sent as HTTPX auth on requests to the wrapped API.
server_auth OPENBB_MCP_SERVER_AUTH tuple[string, string] None (username, password) required as Authorization: Bearer <base64(username:password)> on HTTP requests.

Note: Runtime argument keys, in general, "-" and "_" are interchangeable. Nested uvicorn arguments should use _.

Tool Categories

The server organizes OpenBB tools into categories based on the included API Routers (paths). Categories depend on the installed extensions, but will be the first path in the API after the given prefix.

For example:

  • equity - Stock data, fundamentals, price history, estimates
  • crypto - Cryptocurrency data and analysis
  • economy - Economic indicators, GDP, employment data
  • news - Financial news from various sources
  • fixedincome - Bond data, rates, government securities
  • derivatives - Options and futures data
  • etf - ETF information and holdings
  • currency - Foreign exchange data
  • commodity - Commodity prices and data
  • index - Market indices data
  • regulators - SEC, CFTC regulatory data

Each category contains subcategories that group related functionality (e.g., equity_price, equity_fundamental, etc.).

Tool names come from the route path after the API prefix, skipping {placeholder} segments: /equity/price/historical is equity_price_historical, /economy/cpi is economy_cpi, and a single-segment /hello is hello_hello. When one path serves several methods, the non-GET tools get a _<method> suffix (demo_items and demo_items_post). A route's mcp_config.name replaces the generated name.

Root Tools

These tools are always listed, next to the OpenBB tools or, with discovery, in their place.

  • available_categories: List all tool categories with subcategory names and tool counts.

  • available_tools: List tools in a specific category (and optional subcategory).

    • category: Category of tools to list.
    • subcategory: Optional subcategory. Use general for tools directly under the category.
    • Returns each tool's name with a one-sentence description.
  • search_tools: Find tools with a natural-language query.

    • query: What the tool should do.
    • Returns the full definitions of the best matches, including their input schemas.
  • call_tool: Run any tool by name.

    • name: Tool name.
    • arguments: Dictionary of the tool's arguments.
  • list_prompts: List all available prompts with their arguments.

  • get_prompt: Render a prompt.

    • name: Name of the prompt.
    • arguments: Optional dictionary of argument values.
  • list_resources / read_resource: List resources and read one by uri, including the skill:// guides.

  • install_skill: Write a skill (SKILL.md plus supporting files) into the bundled or a vendor skills directory.

    • skill_name: Lowercase letters, digits, underscores, and hyphens.
    • files: Relative file paths inside the skill directory mapped to their content; paths that leave the directory are refused.
    • target: bundled (default) or a loaded vendor provider name.
    • Any connected client can call it, and it writes to the server's disk, so leave the skills directories read-only for the server process, or serve behind server_auth, when clients are untrusted.
  • run_pipeline: Run tools in sequence on the server, feeding earlier steps' results into later steps' arguments.

    • steps: List of {"id", "tool", "arguments", "inputs"}, where inputs maps an argument name to an earlier step's id.
    • outputs: Optional list of step ids to return. Defaults to the last step.

available_categories, available_tools, search_tools, and call_tool exist only with tool discovery.

openbb-cli Dispatcher Tools

When openbb-cli is installed (pip install "openbb-mcp-server[cli]") and enable_cli_tools is on, four more tools run commands through the CLI's dispatcher, in process or against a remote openbb-api server:

  • openbb_dispatch: Run one command (command, params).
  • openbb_batch_dispatch: Run a list of commands concurrently (requests).
  • openbb_list_commands: List every command with a one-line description.
  • openbb_describe_command: Describe one command's parameters and output schema (command, optional provider).

Each takes an optional server_url, falling back to OPENBB_SERVER_URL, then to the in-process obb.

Data-Processing Tools and Pipelines

Installed data-processing extensions (openbb-technical, openbb-quantitative, openbb-econometrics) are exposed like any other category. Their commands take the rows to analyze as a data argument, so pass them through run_pipeline instead of sending a price history through the conversation. The rows travel between steps on the server, and only the selected outputs come back:

{
    "steps": [
        {
            "id": "prices",
            "tool": "equity_price_historical",
            "arguments": {"symbol": "AAPL", "provider": "yfinance", "start_date": "2025-01-01"}
        },
        {"id": "rsi", "tool": "technical_rsi", "arguments": {"length": 14}, "inputs": {"data": "prices"}},
        {"id": "macd", "tool": "technical_macd", "inputs": {"data": "prices"}}
    ],
    "outputs": ["rsi", "macd"]
}

A step's input is the earlier step's results, a chart artifact's rows, a wrapped result, or its whole output when it has neither. Pipelines are validated before any step runs, and a failing step is reported by its id. Use allowed_tool_categories (or, with tool discovery off, default_tool_categories) to leave the data-processing categories out. run_pipeline calls only tools the server serves: tools hidden by discovery, but not tools outside those categories.

Parameter Choices

Tool input schemas state every parameter's valid values, taken from the provider choices and widget x-widget_config options declared on the command:

  • A parameter with one fixed set of values gets an enum, which clients validate before the call.
  • When providers accept different values, the enum holds all of them and the description lists them by provider.
  • Multi-valued (comma-separated) parameters, and choices only some of a parameter's providers declare, are listed in the description (Valid values for provider oecd (comma-separate several): ...).
  • A parameter whose values come from an options endpoint names the tool that lists them, with the arguments to pass (Get the valid values from the `derivatives_options_strikes` tool with symbol=<the symbol you pass here>.). Options endpoints left out of the API schema have no tool to point to.

Charts

A Plotly figure in a tool result, returned directly or as an OBBject's chart (chart: true), is replaced by an OpenBB Workspace artifact that Copilot renders natively. Line, bar, scatter, pie, and donut figures become a chart artifact whose content rows and chart_params (chartType, xKey, yKey, or angleKey and calloutLabelKey) redraw the figure. Other figures become a table artifact of their data. Tool output schemas declare the artifact in place of the Plotly figure.

{
    "type": "chart",
    "name": "SPY Price Nearest OTM Strikes",
    "description": "Output of the cboe_options_term_structure tool.",
    "uuid": "5b0e1c52-6f3e-4a51-9d6f-0f1b6a2f4c11",
    "content": [{"x": "2026-10-16", "Calls": 4.51}, {"x": "2026-11-20", "Calls": 7.12}],
    "chart_params": {"chartType": "line", "xKey": "x", "yKey": ["Calls"]}
}

Tool Discovery

When enable_tool_discovery is enabled, the OpenBB tools are left out of the tool list and reached through these tools instead:

  1. Browse — available_categories returns the category tree with tool counts.
  2. Inspect — available_tools lists every tool in a category with a one-sentence description.
  3. Search — search_tools finds tools by a natural-language query and returns their full definitions, including the input schema.
  4. Call — call_tool runs any tool by name with its arguments. A hidden tool can also be called directly by name.

Discovery holds no per-session state, so it behaves the same for every client and transport — including stateless MCP clients — and is safe for multi-user deployments.

For scenarios where you want discovery available, enable it with --tool-discovery. Otherwise the server runs with a fixed toolset and you can control the available tools via allowed_tool_categories and default_tool_categories.

System Prompt

A system prompt file can be added on initialization, or defined in the configuration file, or as an environment variable. It should be a valid, relative or absolute, path to a .txt file.

The system prompt is made available as a resource, resource://system_prompt, and as the system_prompt prompt listed by list_prompts.

Clients will not automatically use the system prompt, instruct them to use it as part of their onboarding and orientation.

Skills

The server ships with a set of bundled skill guides — Markdown documents that teach an agent how to perform complex multi-step tasks with the OpenBB Platform. Skills are exposed as MCP resources and are discoverable via list_resources().

Each skill is available at a URI of the form skill://<name>/SKILL.md.

Bundled Skills

Skill URI Description
develop_extension skill://develop_extension/SKILL.md Step-by-step guide for building an OpenBB Platform extension.
build_workspace_app skill://build_workspace_app/SKILL.md Guide for building and running OpenBB Workspace applications.
configure_mcp_server skill://configure_mcp_server/SKILL.md Reference for configuring and customising the OpenBB MCP Server.
work_with_server skill://work_with_server/SKILL.md Practical guide for working with the OpenBB MCP Server as an agent.
use_openbb_cli skill://use_openbb_cli/SKILL.md Guide to the openbb command line, .spec files, and spec-driven proxy mode.

When any skills are loaded and no system_prompt_file is configured, the server automatically adds a brief default system prompt that nudges the agent to discover available skills.

Skill Settings

Setting Description
default_skills_dir Path to the bundled skills directory. Set to null or an empty string to disable loading the built-in skills.
skills_reload Set to true to reload skill files from disk on every read — useful when authoring or iterating on skill content.
skills_providers A list of vendor skill provider short-names. Supported values: claude, cursor, vscode, copilot, codex, gemini, goose, opencode.

Example — disable bundled skills:

{
  "default_skills_dir": null
}

Example — load vendor skill providers:

{
  "skills_providers": ["claude", "cursor"]
}

Example — enable skill reload during development:

OPENBB_MCP_SKILLS_RELOAD=true

Server Prompts

A server prompts file can be added on initialization, or defined in the configuration file, or as an environment variable. It should be a valid, relative or absolute, path to a .json file with a list of prompt definitions.

Each entry in the JSON file is a dictionary with the following properties:

  • name: Name of the prompt.
  • description: A brief description of the prompt.
  • content: The content for rendering the prompt.
  • arguments: Optional list of arguments.
    • name: Name of the argument.
    • type: Simple Python type as a string - i.e, "int".
    • default: Supplying a default value makes the parameter Optional; arguments without one are required.
    • description: Description of the parameter. Supply need-to-know details for the LLM.
  • tags: List of tags to apply to the prompt.

Prompts here should provide the LLM a clear path for executing a workflow combining multiple tools or steps, for example:

[
    {
      "name": "equity_analysis",
      "description": "Perform a comprehensive equity analysis using multiple data sources and metrics",
      "content": "Conduct a comprehensive analysis of {symbol} for {analysis_period}. Follow this workflow:\n1. First, get basic stock quote and recent price performance using equity_price_performance.\n2. Retrieve fundamental data including financial statements, ratios, and key metrics using [equity_fundamental_ratios, equity_fundamental_metrics, equity_fundamental_balance].\n3. Gather recent news and analyst estimates for the company using [news_company, equity_estimates_price_target].\n4. Compare valuation metrics with industry peers using equity_compare_peers.\n5. Summarize findings with investment recommendation.\n\nFocus areas: {focus_areas}\nRisk tolerance: {risk_tolerance}",
      "arguments": [
        {
          "name": "symbol",
          "type": "str",
          "description": "Stock ticker symbol to analyze (e.g., AAPL, TSLA)"
        },
        {
          "name": "analysis_period",
          "type": "str",
          "default": "last 12 months",
          "description": "Time period for the analysis"
        },
        {
          "name": "focus_areas",
          "type": "str",
          "default": "growth, profitability, valuation",
          "description": "Specific areas to focus on in the analysis"
        },
        {
          "name": "risk_tolerance",
          "type": "str",
          "default": "moderate",
          "description": "Risk tolerance level: conservative, moderate, or aggressive"
        }
      ],
      "tags": ["equity", "analysis", "comprehensive"]
    }
]

An invalid prompt definition, or prompt argument, will be logged to the console as an error. The item will be ignored, and will not raise an error.

Inline Prompts

Prompts can be added to an endpoint through the openapi_extra dictionary.

Adding prompts here will help the LLM use the endpoint for specific purposes, with less reasoning overhead.

Direct it to get_prompt, or to make note that helpful prompts may be included in the tool's metadata.

The block below assumes app is an instance of FastAPI

@app.get(
    "/economy/gdp",
    openapi_extra={
        "mcp_config": {
            "prompts": [
                {
                    "name": "gdp_summary_prompt",
                    "description": "Generate a brief summary of GDP for a country.",
                    "content": "Provide a concise summary of the GDP for {country} over the last {years} years.",
                    "arguments": [
                        {
                            "name": "years",
                            "type": "int",
                            "default": 5,
                            "description": "Number of years to summarize.",
                        }
                    ],
                    "tags": ["economy", "gdp", "summary"],
                },
                {
                    "name": "gdp_comparison_prompt",
                    "description": "Compare the GDP of two countries.",
                    "content": "Compare the GDP growth of {country1} and {country2}.",
                    "arguments": [
                        {
                            "name": "country1",
                            "type": "str",
                            "description": "First country for comparison.",
                        },
                        {
                            "name": "country2",
                            "type": "str",
                            "description": "Second country for comparison.",
                        },
                    ],
                    "tags": ["economy", "gdp", "comparison"],
                },
            ]
        }
    },
)
def get_gdp_data(country: str, period: Literal["annual", "quarterly"] = "annual"):
    """Get GDP data for a specific country."""
    return {"country": country, "period": period}

Along with being added to list_prompts, prompts will be included with the tool's metadata, returned by list_tools.

Each {placeholder} in content becomes an argument: a prompt argument of the same name, else the endpoint parameter, else a required string. Arguments without a default are required. Prompts name the route's tool, including a name set with mcp_config.name.

The tool description for economy_gdp then ends with:

**Associated Prompts:**
- **gdp_summary_prompt**: Generate a brief summary of GDP for a country.
  - Arguments: `country`, `years`
- **gdp_comparison_prompt**: Compare the GDP of two countries.
  - Arguments: `country1`, `country2`

Use a prompt with the get_prompt tool. MCP passes prompt arguments as strings, so quote every value:

{
  "name": "gdp_summary_prompt",
  "arguments": {
    "years": "10",
    "country": "Japan"
  }
}

Which outputs:

{
  "messages": [
    {
      "role": "user",
      "content": "Use the tool, economy_gdp, to perform the following task.\n\nProvide a concise summary of the GDP for Japan over the last 10 years."
    }
  ]
}

Inline MCP Configuration

In addition to defining prompts, the openapi_extra.mcp_config dictionary allows for more granular control over how your FastAPI routes are exposed as MCP tools. By using the MCPConfigModel, you can validate your configuration and access several powerful properties to customize tool behavior.

It can be imported with:

from openbb_mcp_server.models.mcp_config import MCPConfigModel

Including this configuration in the openapi_extra slot will override any automatically generated value. You only need to enter the values that you wish to customize.

Below are the properties you can define within mcp_config:

The configuration is read from openapi_extra["mcp_config"], or from openapi_extra["x-mcp"] when mcp_config is absent.

  • expose (Optional[bool]): Set to False to completely hide a route from the MCP server. This is useful for internal or deprecated endpoints that should not be available as tools.

  • mcp_type (Optional[MCPType]): Classify the route as a specific MCP type. Valid options are "tool", "resource", or "resource_template".

  • methods (Optional[list[HTTPMethod]]): The HTTP methods of the route to serve; the route's other methods are left out. If omitted, all of the route's methods are served. Valid methods include "GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", and * (for all). When a path serves several methods, the non-GET tools get a _<method> suffix.

  • exclude_args (Optional[list[str]]): Argument names left out of the tool's input schema, for parameters that are handled internally or are not relevant to the end-user. The route's default applies, so every excluded argument needs one.

  • name (Optional[str]): The tool name, replacing the one built from the path.

  • tags (Optional[list[str]]): Tags added to the tool next to its category.

  • enable (Optional[bool]): With tool discovery off, serve (True) or hide (False) the tool regardless of default_tool_categories.

  • describe_responses (Optional[bool]): Keep (True) or cut (False) the response documentation in the tool description, overriding the describe_responses setting.

  • mime_type (Optional[str]): The MIME type of a route served as a resource.

  • prompts (Optional[list[dict[str, str]]]): List of prompts specific to the endpoint. Keys for a prompt are:

    • name: Name of the prompt.
    • description: A brief description of the prompt.
    • content: The content for rendering the prompt. Endpoint parameters are inferred by placeholders.
    • arguments: Optional list of arguments. Items can be exclusive to the prompt, and not referenced in the endpoint.
      • name: Name of the argument.
      • type: Simple Python type as a string - i.e, "int".
      • default: Supplying a default value makes the parameter Optional; arguments without one are required.
      • description: Description of the parameter. Supply need-to-know details for the LLM.
    • tags: List of tags to apply to the prompt.

MCPConfigModel Validation

Values will be validated by the model before including in the server. Invalid configurations will be logged to the console as an error, and the inline definition will be ignored.

ERROR    Invalid MCP config found in route, 'GET /equity/price'. Skipping tool customization because of validation error ->
          1 validation error for MCPConfigModel
          mcp_type
            Input should be 'tool', 'resource' or 'resource_template' [type=enum, input_value='some_setting', input_type=str]
              For further information visit https://errors.pydantic.dev/2.11/v/enum

Example

Here is an example demonstrating how to use these properties to fine-tune a tool’s behavior:

@app.get(
    "/some/route",
    openapi_extra={
        "mcp_config": {
            "expose": True,
            "mcp_type": "tool",
            "methods": ["GET"],
            "exclude_args": ["internal_param"],
            "prompts": [
                {
                    "name": "some_route_prompt",
                    "description": "Summarize the route's output for a value.",
                    "content": "Summarize the output of some_route for {param1}.",
                }
            ],
        }
    },
)
def some_route(param1: str, internal_param: str = "default"):
    """An example route with advanced MCP configuration."""
    return {"param1": param1}

In this example, the /some/route endpoint is explicitly exposed as a tool for the GET method only, and the internal_param argument is hidden from the tool’s interface.

Client Examples

Start the server with the appropriate transport and configuration for the client, the default transport is streamable-http, served at http://127.0.0.1:8001/mcp.

# Start with default settings
openbb-mcp

# Use an alternative transport
openbb-mcp --transport sse

# Start with specific categories and custom host/port
openbb-mcp --default-categories equity,news --host 0.0.0.0 --port 8080

# Start with allowed categories restriction
openbb-mcp --allowed-categories equity,crypto,news

# Hide the tools behind search_tools and call_tool
openbb-mcp --tool-discovery

Claude Desktop

To connect the OpenBB MCP server with Claude Desktop, you need to configure it as a custom tool server. Here are the steps:

  1. Locate the settings or configuration file for Claude Desktop where you can define custom MCP servers.

  2. Add the following entry to your mcpServers configuration. This will configure Claude Desktop to launch the OpenBB MCP server automatically using stdio for communication.

    {
      "mcpServers": {
        "openbb-mcp": {
          "command": "uvx",
          "args": [
            "--from",
            "openbb-mcp-server",
            "--with",
            "openbb",
            "openbb-mcp",
            "--transport",
            "stdio"
          ]
        }
      }
    }
    
  3. Ensure that uvx, is installed and available in your system's PATH. If not, follow the installation instructions.

  4. Restart Claude Desktop to apply the changes. You should now see "openbb-mcp" as an available tool source.

Cursor

To use OpenBB tools within Cursor, you first need to run the MCP server and then tell Cursor how to connect to it.

Step 1: Run the OpenBB MCP Server

Open your terminal and start the server. You can use the default settings or customize it.

For a default setup, run:

openbb-mcp

The server will start on http://127.0.0.1:8001.

Step 2: Configure Cursor

Add the following configuration to the mcpServers object in your mcp.json file. If the mcpServers object doesn't exist, you can add it.

{
  "mcpServers": {
    "openbb-mcp": {
      "url": "http://localhost:8001/mcp"
    }
  }
}

VS Code

Step 1: Enable MCP in VS Code Settings

Enter shift + command + p and open "Preferences: Open User Settings"

Search for "mcp", and the item should show up under "Chat". Check the box to enable MCP server integrations.

vs-code-mcp-enable

Step 2: Run the OpenBB MCP Server

Open your terminal and start the server. You can use the default settings or customize it.

For a default setup, run:

openbb-mcp

The server will start on http://127.0.0.1:8001.

Step 3: Add Server as HTTP

Enter shift + command + p and select "MCP: Add Server".

vs-code-mcp-commands

Press enter and then select HTTP.

vs-code-mcp-add-http

Copy the URL from the console of the running server, and enter it

INFO     Starting MCP server 'OpenBB MCP' with transport 'streamable-http' on http://127.0.0.1:8001/mcp

Give it a name, and add it either as global or to a workspace. The end result will create a mcp.json VS Code configuration file for the chosen domain.

vs-code-mcp-json

The tools can now be added as context to the chat.

vs-code-mcp-tools

Note: When adding to the Cline extension, set --transport sse when starting the server.