Аннотация:
В этой статье мы разберёмся, как развернуть собственный MCP‑сервер на основе FastAPI, подключить его к Cursor‑Agent и дать LLM‑модели возможность динамически вызывать ваши инструменты — например, получать данные мониторинга или генерировать unit‑тесты на лету. Также покажем, как использование BitDive помогает ещё глубже анализировать трассы вызовов и повышать качество тестов.
Почему MCP и Cursor
Современные LLM‑агенты могут обходиться без внешних вызовов — выдавать ответы исключительно на основе prompt’а. Но когда речь идёт о живых данных (трассы вызовов, результаты SQL‑запросов, исходный код из GitLab), нужно динамически обогащать контекст модели и давать ей «функции» для вызова.
MCP (Model‑Context Protocol) описывает, как ваши инструменты («tools») сообщаются агенту: JSON‑схемы + HTTP‑эндпоинты + SSE‑канал для discovery.
Cursor‑Agent (IDE‑плагин или standalone) может подписаться на ваш MCP‑сервер, получить список функций и автоматически проксировать их вызовы к реальной логике.
Это даёт вам:
Централизацию всех инструментов LLM в одном месте.
Гибкое управление доступом и аудитом всех вызовов.
Возможность декуплирования бизнес‑логики от обогащения prompt’а и post‑processing ответов модели.
Роль BitDive в экосистеме мониторинга
BitDive — это высокопроизводительная платформа мониторинга и трассировки, разработанная командой BitDive . Она сочетает в себе:
ByteBuddy‑инструментацию: перехват HTTP, REST, SQL, Kafka и вызовов методов в рантайме.
Цепочки вызовов: хранение полного дерева вызовов с параметрами и результатами.
Горячие точки производительности: автоматический анализ длительных операций и визуализация в UI.
GitLab‑интеграцию: возможность подгружать исходники, находить участки кода по trace_id и строить ссылки в merge request.
Используя BitDive совместно с MCP‑сервером, LLM‑ассистент получает не просто сырые данные, а уже обогащённые контекстом трассы с точки зрения производительности и защищённости, что позволяет генерировать более точные и релевантные unit‑тесты.
Проблематика на примере мониторинга
Предположим, у вас есть система мониторинга, которая:
С помощью ByteBuddy и AOP перехватывает REST‑вызовы, SQL‑запросы и цепочки методов.
Хранит полные трассы вызовов (
trace_id → list<MethodCall>
).В BitDive вы уже видите UI с деталями — но хотите подтянуть эти данные внутрь LLM для автоматической генерации тестов и анализа «узких мест».
Задачи:
Получить трассу по
trace_id
(из BitDive).Сгенерировать unit‑тест, опираясь на содержимое трассы и метрики.
Сделать быстрый анализ «горячих точек» производительности.
Как это реализовать без громоздкой ручной подстановки данных в prompt?
В этом поможет связка MCP + Cursor + BitDive.
Шаг 1. Реализация MCP‑сервера на FastAPI
from fastapi import FastAPI, Request, Header, HTTPException
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import os, asyncio
app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"])
API_KEY = os.getenv("API_KEY", "secret-token")
# 1) Discovery: список JSON‑схем инструментов
@app.get("/v1/tools")
async def list_tools(authorization: str = Header(None)):
if authorization != f"Bearer {API_KEY}":
raise HTTPException(401, "Unauthorized")
return [
{
"name": "get_trace",
"description": "Получить трассировку по trace_id из BitDive",
"parameters": {
"type": "object",
"properties": {
"trace_id": {"type": "string", "description": "ID трассы"}
},
"required": ["trace_id"]
}
},
{
"name": "generate_test",
"description": "Сгенерировать unit-тест на основе трассы и метрик BitDive",
"parameters": {
"type": "object",
"properties": {
"trace": {"type": "string", "description": "Сериализованная трасса с метриками"}
},
"required": ["trace"]
}
}
]
# 2) SSE‑канал: Cursor подписывается и ждёт обновлений
@app.get("/v1/events")
async def events(request: Request):
async def gen():
yield "event: ready\ndata: {}\n\n"
while not await request.is_disconnected():
await asyncio.sleep(1)
return app.response_class(gen(), media_type="text/event-stream")
# 3) Вызов get_trace
@app.post("/v1/tools/get_trace")
async def get_trace(body: dict, authorization: str = Header(None)):
if authorization != f"Bearer {API_KEY}":
raise HTTPException(401, "Unauthorized")
trace_id = body["trace_id"]
# интеграция с BitDive API: запрос трассы + метрик
bitdive_data = fetch_from_bitdive(trace_id)
return JSONResponse({"trace": bitdive_data})
# 4) Вызов generate_test
@app.post("/v1/tools/generate_test")
async def generate_test(body: dict, authorization: str = Header(None)):
if authorization != f"Bearer {API_KEY}":
raise HTTPException(401, "Unauthorized")
trace = body["trace"]
# запускаем локальную генерацию или обращаемся в LLM
test_code = generate_test_from_trace(trace)
return JSONResponse({"test": test_code})
Запускаем:
export API_KEY=super-secret
pip install fastapi uvicorn
uvicorn mcp_server:app --reload --port 8000
Шаг 2. Настройка Cursor
Settings → MCP → MCP Servers → Add new MCP Server.
-
Заполняем:
Name:
local-mcp
Events URL:
http://localhost:8000/v1/events
Auth Header:
Bearer super-secret
Сохраняем. Cursor подключится к SSE и запросит
/v1/tools
, включая описания BitDive‑орiented функций.
Шаг 3. Пример диалога с агентом
Пользователь:
Напиши unit‑тест для трассы сcallId="abc123"
.
Cursor→LLM с функциями: get_trace, generate_test
LLM→Cursor (function_call get_trace)
Cursor→MCP /v1/tools/get_trace → BitDive API → возвращает трассу с задержками и SQL
Cursor→LLM (trace) → LLM сама решает вызвать generate_test
Cursor→MCP /v1/tools/generate_test → возвращает Java‑код теста с проверками по данным BitDive
Cursor→LLM→Пользователь: готовый unit‑тест, включающий проверки задержек и SQL‑запросов из BitDive.
Выводы и рекомендации
BitDive + MCP дают LLM‑ассистенту контекст не просто вызовов, а обогащённые метриками производительности и безопасности.
Автоматизация. LLM‑агент сам решает, когда и какой инструмент вызвать.
Гибкость. Новый инструмент — и он сразу доступен модели.
Аудит и безопасность. Все вызовы проходят через централизованный прокси с логированием.
Расширяемость. Можно добавить инструменты для анализа hot‑spots, поиска кода, тестирования сценариев.