Skip to content

Migrate LumiBot MCP runtime to protocol v2 - #1147

Open
mpelteshki wants to merge 1 commit into
devfrom
feat/mcp-2026-07-28
Open

Migrate LumiBot MCP runtime to protocol v2#1147
mpelteshki wants to merge 1 commit into
devfrom
feat/mcp-2026-07-28

Conversation

@mpelteshki

@mpelteshki mpelteshki commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary\n\n- migrate HTTP and stdio MCP connections to official protocol-v2 client\n- remove initialize/session flow and duplicate raw HTTP fallback\n- preserve bearer and custom headers through one client path\n- update public docs, dependency bounds, and transport fixtures\n\n## Performance\n\n- focused MCP suite: 9.02s baseline wall → 7.48s after\n- final verification: 6 passed in 6.25s\n\n## Verification\n\n- focused HTTP and stdio MCP tests\n- changed-line review; repository lint still reports old untouched runtime/test violations\n- diff checks

Summary by CodeRabbit

  • New Features

    • Updated MCP integrations to support the modern 2026-07-28 protocol.
    • Added automatic protocol discovery and compatibility with older conforming servers.
    • Enabled stateless, POST-based HTTP communication with improved metadata and timeout handling.
  • Documentation

    • Added guidance for configuring and validating modern MCP connections.
    • Documented protocol headers, discovery checks, authentication, and migration considerations.
  • Tests

    • Expanded coverage for discovery, headers, metadata, tool results, and legacy behavior removal.

@mpelteshki
mpelteshki requested a review from grzesir as a code owner August 12, 2026 14:47
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The MCP integration now uses the official Python MCP v2 client and MCP 2026-07-28 transport contract. It negotiates with server/discover, sends stateless POST requests, removes initialization and session handling, and validates modern and legacy server compatibility.

Changes

MCP v2 client migration

Layer / File(s) Summary
Transport contract and dependency update
requirements.txt, setup.py, docs/MCP_2026_TRANSPORT.md, docs/AI_TRADING_AGENTS.md, CHANGELOG.md, docsrc/botspot_mcp.rst
The project requires MCP 2.x and httpx2. Documentation describes discovery, stateless POST requests, protocol headers, request metadata, fallback behavior, and removed session semantics.
Unified MCP client runtime
lumibot/components/agents/runtime.py
MCP connections use MCPClient, shared implementation metadata, automatic negotiation, configured timeouts, model serialization, and httpx2.AsyncClient for HTTP transports. Tool listing and invocation use the unified client.
Transport and protocol validation
tests/test_agent_runtime_mcp_transports.py, tests/test_agent_runtime_remote_mcp.py
Tests use MCP v2 server and client APIs. Remote transport tests validate discovery, headers, metadata, typed results, and the absence of initialize and session headers.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AgentRuntime
  participant MCPClient
  participant HTTPTransport
  participant MCPServer
  AgentRuntime->>MCPClient: Create client with automatic mode and metadata
  MCPClient->>MCPServer: Negotiate with server/discover
  MCPClient->>HTTPTransport: Send stateless POST request
  HTTPTransport->>MCPServer: Forward JSON-RPC with protocol headers and _meta
  MCPServer-->>HTTPTransport: Return tool result
  HTTPTransport-->>MCPClient: Return response
  MCPClient-->>AgentRuntime: Return serialized tool data
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: migrating the LumiBot MCP runtime to protocol v2.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mcp-2026-07-28

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_agent_runtime_remote_mcp.py`:
- Around line 74-81: Update the test fixture’s request handler around do_POST
and the corresponding GET/DELETE handlers to record every MCP request, including
method and headers/body as applicable. Add assertions in the affected tests that
all recorded MCP requests use POST, so standalone GET streams and DELETE session
cleanup are explicitly rejected.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b94a2e0f-2c58-4d26-a862-6b6ec835b01f

📥 Commits

Reviewing files that changed from the base of the PR and between 07b2514 and 2722c92.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • docs/AI_TRADING_AGENTS.md
  • docs/MCP_2026_TRANSPORT.md
  • docsrc/botspot_mcp.rst
  • lumibot/components/agents/runtime.py
  • requirements.txt
  • setup.py
  • tests/test_agent_runtime_mcp_transports.py
  • tests/test_agent_runtime_remote_mcp.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (20)
**/*.{py,md,rst,txt,yml,yaml,json,ini,env}

📄 CodeRabbit inference engine (CLAUDE.md)

Never fabricate, synthesize, forward-fill, interpolate, or default-fill missing market data in backtests; return empty / explicit absence instead, and remove any code that returns fake bars as real data.

Files:

  • setup.py
  • requirements.txt
  • docs/MCP_2026_TRANSPORT.md
  • CHANGELOG.md
  • docsrc/botspot_mcp.rst
  • tests/test_agent_runtime_remote_mcp.py
  • docs/AI_TRADING_AGENTS.md
  • tests/test_agent_runtime_mcp_transports.py
  • lumibot/components/agents/runtime.py
**/*.{py,md,rst}

📄 CodeRabbit inference engine (CLAUDE.md)

If an environment variable is introduced or changed, make sure both engineering and public documentation stay synchronized with the new behavior.

Files:

  • setup.py
  • docs/MCP_2026_TRANSPORT.md
  • CHANGELOG.md
  • docsrc/botspot_mcp.rst
  • tests/test_agent_runtime_remote_mcp.py
  • docs/AI_TRADING_AGENTS.md
  • tests/test_agent_runtime_mcp_transports.py
  • lumibot/components/agents/runtime.py
setup.py

📄 CodeRabbit inference engine (CLAUDE.md)

Treat the version= value in setup.py as the authoritative project version source of truth.

Treat the version= value in setup.py as the authoritative package version source.

Files:

  • setup.py
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Never commit private, account-specific, machine-specific, or credential-related information to tracked repository files; use placeholders and public environment-variable names instead. Rotate exposed credentials immediately.
Keep sensitive BotSpot/Lumiwealth operational credentials and private references in private repositories or secret stores, not the public LumiBot checkout.
Normal work must remain in the canonical checkout on the latest active version/X.Y.Z branch; do not create sibling worktrees, switch branches, or create additional branches without explicit authorization.
Do not create, manage, merge, close, or take over pull requests, publish releases, tag, deploy, update package versions, or modify downstream pins without explicit authorization.
Never push directly to dev; authorized release captains must use the approved version-branch release workflow.
Never run git checkout or destructive operations such as git reset --hard, git clean -f, or git stash; inspect dirty files and preserve other agents' changes.
Commit coherent changes in small logical chunks, review all diffs before committing, and coordinate overlapping tests, baselines, and CI workflow changes through handoffs.
Never delete shared caches; use versioned S3 namespaces for cold-cache simulations and delete cache objects only when explicitly requested and tightly scoped.
If a new environment variable is genuinely required for a user-facing feature, document it in docsrc/environment_variables.rst and relevant engineering notes.
Never launch ThetaTerminal locally with production credentials; local ThetaData credentials must remain untracked, use disposable $TMPDIR files when necessary, and never be used for backtests.
Wrap long pytest, backtest, and stress commands with bin/safe-timeout 1200s or another timeout wrapper, splitting work when practical.
Capture reproducible demonstration artifacts such as strategy/library logs, tear sheets, and downloader stress JSON files when showing fixe...

Files:

  • setup.py
  • requirements.txt
  • docs/MCP_2026_TRANSPORT.md
  • CHANGELOG.md
  • docsrc/botspot_mcp.rst
  • tests/test_agent_runtime_remote_mcp.py
  • docs/AI_TRADING_AGENTS.md
  • tests/test_agent_runtime_mcp_transports.py
  • lumibot/components/agents/runtime.py
**/*.{py,yml,yaml,json,md,rst}

📄 CodeRabbit inference engine (AGENTS.md)

Document and test behavioral changes in the same change set, including regression tests and comments for non-obvious invariants.

Files:

  • setup.py
  • docs/MCP_2026_TRANSPORT.md
  • CHANGELOG.md
  • docsrc/botspot_mcp.rst
  • tests/test_agent_runtime_remote_mcp.py
  • docs/AI_TRADING_AGENTS.md
  • tests/test_agent_runtime_mcp_transports.py
  • lumibot/components/agents/runtime.py
**/*.{py,md,rst,log}

📄 CodeRabbit inference engine (AGENTS.md)

Never hardcode private downloader URLs; use localhost or placeholders and refer to DATADOWNLOADER_BASE_URL.

Files:

  • setup.py
  • docs/MCP_2026_TRANSPORT.md
  • CHANGELOG.md
  • docsrc/botspot_mcp.rst
  • tests/test_agent_runtime_remote_mcp.py
  • docs/AI_TRADING_AGENTS.md
  • tests/test_agent_runtime_mcp_transports.py
  • lumibot/components/agents/runtime.py
**

⚙️ CodeRabbit configuration file

**: Review every pull request as if LumiBot is a public open-source trading framework.
Prioritize real bugs, security/privacy issues, user-facing regressions, and release risk.

Always check changed lines for:

  • hardcoded credentials, API keys, tokens, account emails, private URLs, private hostnames, local credential paths, or personal filesystem paths;
  • accidental leakage of BotSpot, Lumiwealth, customer, broker, paid-vendor, CI, or maintainer-only operational details into public code/docs/tests;
  • code that logs, prints, persists, screenshots, or commits secrets or customer/broker data;
  • test fixtures or docs that look fake but could be copied into real usage as credentials or private endpoints;
  • changes that weaken authentication, authorization, data-source safety, broker/order safety, or CI/release gates.

If a finding depends on repository context, explain the specific source file and invariant instead of giving generic advice.

Files:

  • setup.py
  • requirements.txt
  • docs/MCP_2026_TRANSPORT.md
  • CHANGELOG.md
  • docsrc/botspot_mcp.rst
  • tests/test_agent_runtime_remote_mcp.py
  • docs/AI_TRADING_AGENTS.md
  • tests/test_agent_runtime_mcp_transports.py
  • lumibot/components/agents/runtime.py
**/*.{png,jpg,jpeg,webp,gif,svg,md,rst}

📄 CodeRabbit inference engine (CLAUDE.md)

For any generated or AI-edited image or documentation visual, use Nano Banana MCP only; do not use fallback image generators, Mermaid screenshots, or manual diagram pipelines, and visually inspect every output before committing.

Files:

  • docs/MCP_2026_TRANSPORT.md
  • CHANGELOG.md
  • docsrc/botspot_mcp.rst
  • docs/AI_TRADING_AGENTS.md
docs/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

When a workflow changes (including environment variables, cache semantics, or harness flags), update the relevant docs/* page in the same change set.

Files:

  • docs/MCP_2026_TRANSPORT.md
  • docs/AI_TRADING_AGENTS.md
docs/**/*.{md,rst}

📄 CodeRabbit inference engine (CLAUDE.md)

When touching code, proactively check both docs/ and docsrc/ for gaps and update both locations if the behavior, API, or workflow changed.

Files:

  • docs/MCP_2026_TRANSPORT.md
  • docs/AI_TRADING_AGENTS.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/**/*.md: Use uppercase underscore-separated documentation filenames, with date-first names for handoffs and investigations.
New docs must begin with a title, one-line description, Last Updated date, Status, Audience, and an Overview section.
For every LumiBot code change, check and update engineering documentation as needed, including architecture, investigations, handoffs, and behavioral rationale.

Files:

  • docs/MCP_2026_TRANSPORT.md
  • docs/AI_TRADING_AGENTS.md
docs/**

⚙️ CodeRabbit configuration file

docs/**: Documentation is public. Flag private paths, credential examples, internal account
emails, private endpoints, stale security claims, or operational details that should
live only in private runbooks.

Files:

  • docs/MCP_2026_TRANSPORT.md
  • docs/AI_TRADING_AGENTS.md
CHANGELOG.md

📄 CodeRabbit inference engine (CLAUDE.md)

Update CHANGELOG.md for every deployment, release, or significant change, and include changes from all contributors since the last version bump.

Update CHANGELOG.md for every deployment, release, significant bug fix, feature, breaking change, performance change, or dependency update, including all contributors' changes since the previous version.

Files:

  • CHANGELOG.md
docsrc/**/*.rst

📄 CodeRabbit inference engine (CLAUDE.md)

docsrc/**/*.rst: When making user-facing changes, update the relevant Sphinx docs under docsrc/ (for example brokers, strategy methods, lifecycle methods, entities, backtesting, FAQ, common mistakes, getting started, or deployment pages).
For user-facing behavior changes, keep public documentation examples, parameters, return values, and edge cases current, and build the docs locally to verify rendering when applicable.

Update the relevant public Sphinx documentation whenever user-facing behavior, APIs, brokers, data sources, lifecycle methods, properties, environment variables, or deployment behavior changes.

Files:

  • docsrc/botspot_mcp.rst
docsrc/**

⚙️ CodeRabbit configuration file

docsrc/**: Sphinx documentation is public. Flag private paths, credential examples, internal
account emails, private endpoints, stale security claims, or operational details that
should live only in private runbooks.

Files:

  • docsrc/botspot_mcp.rst
tests/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

tests/**/*.py: Add unit tests for any new functionality
Ensure high level of test coverage using pytest with coverage reporting
Ensure all tests are well-documented and follow best practices

tests/**/*.py: Treat any test whose earliest commit date is before 2025-06-01 as LEGACY. For LEGACY tests, fix the code, not the test. Only change a LEGACY test when you can clearly justify that the old expectation was incorrect or behavior was intentionally changed for correctness, and document it in the test file.
Treat any test whose earliest commit date is before 2025-01-01 as FROZEN LEGACY (effectively 'do not change'). Only change a FROZEN LEGACY test in exceptional cases and include a clear write-up in the test and PR.
If you change any expected values or assertions in a test, add a short note near the change explaining why (what changed, and why the new expectation is correct). Prefer making the test more robust (less brittle) over updating magic numbers.

Consider test age when resolving failures: tests older than one year generally require code fixes, while newer-test conflicts require investigation and documented judgment.

Files:

  • tests/test_agent_runtime_remote_mcp.py
  • tests/test_agent_runtime_mcp_transports.py
tests/**/*.{py,sh}

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.{py,sh}: Do not add environment variables solely to skip or disable tests; use existing pytest markers and clear normal skips instead.
Backtests and tests must configure DATADOWNLOADER_BASE_URL and DATADOWNLOADER_API_KEY through the runtime environment and must not shortcut through Theta directly.

Files:

  • tests/test_agent_runtime_remote_mcp.py
  • tests/test_agent_runtime_mcp_transports.py
tests/**

⚙️ CodeRabbit configuration file

tests/**: Tests are public. Flag hardcoded real-looking credentials, account emails, personal
paths, private endpoints, and fixtures that could accidentally exercise production or
paid-vendor resources without explicit opt-in.

Files:

  • tests/test_agent_runtime_remote_mcp.py
  • tests/test_agent_runtime_mcp_transports.py
lumibot/**/*.{py,md,rst}

📄 CodeRabbit inference engine (AGENTS.md)

lumibot/**/*.{py,md,rst}: LumiBot broker and data-source adapters exclusively own provider-specific market-data and trading behavior; public strategy and data-source APIs must remain provider-generic.
Keep provider batching, request construction, response parsing, and provider error normalization inside the relevant adapter; never expose BotSpot credentials, Vault references, Node service credentials, or Bot Manager internals in public contracts.
Multi-asset reads must preserve per-symbol success or failure so callers can distinguish returned and missing symbols without substituting another provider.
Measure backtest accuracy against live broker behavior when possible; use vendor parity artifacts only as regression signals, not absolute truth.

Files:

  • lumibot/components/agents/runtime.py
lumibot/**

⚙️ CodeRabbit configuration file

lumibot/**: Review runtime/library changes for trading safety, broker/account isolation, data
correctness, secret handling, and public/private boundary violations. Flag hardcoded
BotSpot-specific behavior unless it is clearly provider-generic and appropriate for
open-source LumiBot.

Files:

  • lumibot/components/agents/runtime.py
🪛 Pylint (4.0.6)
tests/test_agent_runtime_mcp_transports.py

[error] 15-15: No name 'PandasDataBacktesting' in module 'lumibot.backtesting'

(E0611)


[error] 16-16: No name 'AgentRunResult' in module 'lumibot.components.agents'

(E0611)


[error] 16-16: No name 'MCPServer' in module 'lumibot.components.agents'

(E0611)


[error] 17-17: No name 'Asset' in module 'lumibot.entities'

(E0611)


[error] 17-17: No name 'Data' in module 'lumibot.entities'

(E0611)


[error] 18-18: No name 'Strategy' in module 'lumibot.strategies'

(E0611)

lumibot/components/agents/runtime.py

[error] 38-38: No name 'Client' in module 'mcp.client'

(E0611)


[error] 50-50: No name 'streamable_http_client' in module 'mcp.client.streamable_http'

(E0611)

🔇 Additional comments (9)
requirements.txt (1)

45-46: LGTM!

setup.py (1)

104-105: LGTM!

docs/MCP_2026_TRANSPORT.md (1)

1-35: LGTM!

docs/AI_TRADING_AGENTS.md (1)

150-154: LGTM!

CHANGELOG.md (1)

3-10: LGTM!

docsrc/botspot_mcp.rst (1)

25-25: LGTM!

Also applies to: 38-42, 157-170

lumibot/components/agents/runtime.py (1)

4-9: LGTM!

Also applies to: 27-52, 1543-1589, 1608-1618, 1621-1631

tests/test_agent_runtime_mcp_transports.py (1)

1-48: LGTM!

Also applies to: 253-273, 302-322

tests/test_agent_runtime_remote_mcp.py (1)

82-123: LGTM!

Also applies to: 143-143

Comment on lines +74 to +81
requests = []

def do_POST(self):
length = int(self.headers.get("Content-Length", "0"))
body = self.rfile.read(length)
data = json.loads(body.decode("utf-8"))
method = data.get("method")
if method == "tools/list":
self.__class__.requests.append({"body": data, "headers": dict(self.headers)})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Record and reject non-POST MCP traffic.

Line 81 records only POST requests. Lines 186-199 cannot detect a standalone GET stream or session cleanup DELETE request.

Record GET and DELETE requests in the fixture. Assert that every recorded MCP request uses POST.

As per coding guidelines, “Document and test behavioral changes in the same change set, including regression tests and comments for non-obvious invariants.”

Proposed regression coverage
     def do_POST(self):
         length = int(self.headers.get("Content-Length", "0"))
         body = self.rfile.read(length)
         data = json.loads(body.decode("utf-8"))
         method = data.get("method")
-        self.__class__.requests.append({"body": data, "headers": dict(self.headers)})
+        self.__class__.requests.append(
+            {"http_method": "POST", "body": data, "headers": dict(self.headers)}
+        )
         if method == "server/discover":
             ...

+    def do_GET(self):
+        self.__class__.requests.append(
+            {"http_method": "GET", "headers": dict(self.headers)}
+        )
+        self.send_error(405)
+
+    def do_DELETE(self):
+        self.__class__.requests.append(
+            {"http_method": "DELETE", "headers": dict(self.headers)}
+        )
+        self.send_error(405)
+
     ...
     methods = [request["body"]["method"] for request in _MCPHandler.requests]
+    assert {request["http_method"] for request in _MCPHandler.requests} == {"POST"}

Also applies to: 186-199

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_agent_runtime_remote_mcp.py` around lines 74 - 81, Update the test
fixture’s request handler around do_POST and the corresponding GET/DELETE
handlers to record every MCP request, including method and headers/body as
applicable. Add assertions in the affected tests that all recorded MCP requests
use POST, so standalone GET streams and DELETE session cleanup are explicitly
rejected.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant