惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Visual Studio Blog
I
InfoQ
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
D
Docker
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Blog — PlanetScale
Blog — PlanetScale
阮一峰的网络日志
阮一峰的网络日志
宝玉的分享
宝玉的分享
量子位
D
DataBreaches.Net
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hugging Face - Blog
Hugging Face - Blog
J
Java Code Geeks
T
Tailwind CSS Blog
S
Securelist
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
雷峰网
雷峰网
D
Darknet – Hacking Tools, Hacker News & Cyber Security
小众软件
小众软件
Cloudbric
Cloudbric
N
News and Events Feed by Topic
L
LangChain Blog
云风的 BLOG
云风的 BLOG
S
SegmentFault 最新的问题
L
LINUX DO - 热门话题
T
The Blog of Author Tim Ferriss
AWS News Blog
AWS News Blog
爱范儿
爱范儿
博客园 - 聂微东
Project Zero
Project Zero
V
Vulnerabilities – Threatpost
PCI Perspectives
PCI Perspectives
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - Franky
Y
Y Combinator Blog
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
AI
AI
The Last Watchdog
The Last Watchdog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
CXSECURITY Database RSS Feed - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
美团技术团队
Google Online Security Blog
Google Online Security Blog
Google DeepMind News
Google DeepMind News
MyScale Blog
MyScale Blog
T
Tor Project blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
MCP в Cursor IDE: подключаем AI-агенту внешние данные без возни с API
artem · 2026-05-06 · via Все публикации подряд на Хабре

Средний

8 мин

8.7K

Cursor IDE умеет генерировать код, рефакторить, объяснять и дебажить. Но по умолчанию он видит только файлы в вашем проекте. Если нужно, чтобы агент сходил в Google Trends, проверил задачи в Jira или прочитал что-то из Notion, приходится копировать данные руками и вставлять в чат. Агент получается не особо автономным, каждый шаг требует вашего участия.

MCP даёт агенту инструменты — функции, которые тот вызывает сам, когда ему нужны внешние данные. Вместо «вот тебе CSV, проанализируй» вы пишете «проанализируй тренды по запросу X», и агент сам вызывает нужную функцию, получает данные и работает с ними.

Как устроен MCP

MCP — открытый протокол, который стандартизирует подключение инструментов к языковым моделям. До него каждый фреймворк делал по-своему: у LangChain свои tools, у OpenAI function calling, у Cursor свой формат. MCP ввёл единый стандарт.

MCP-сервер — программа, которая запускается локально и экспортирует инструменты через стандартный протокол. Каждый инструмент имеет имя, описание и схему параметров. Cursor видит список инструментов и вызывает нужный, когда считает это полезным для ответа.

Без MCP агент знает только файлы в проекте и ваше сообщение. С MCP он может запросить данные из внешнего API, прочитать документ из базы знаний, выполнить SQL-запрос, вызвать скрипт. Агент сам решает, какой инструмент вызвать, формирует запрос, получает ответ и продолжает работу.

Подключаем MCP-сервер к Cursor

Конфигурация живёт в .cursor/mcp.json в корне проекта:

{
  "mcpServers": {
    "google-trends": {
      "command": "python",
      "args": ["-m", "trends_server"],
      "env": {
        "SERPAPI_KEY": "your-key-here"
      }
    }
  }
}

Cursor запускает сервер как дочерний процесс, общается через stdin/stdout по протоколу MCP. После перезапуска Cursor видит инструменты сервера и может их использовать.

Можно подключить несколько серверов одновременно:

{
  "mcpServers": {
    "google-trends": {
      "command": "python",
      "args": ["-m", "trends_server"]
    },
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "POSTGRES_URL": "postgresql://user:pass@localhost:5432/mydb"
      }
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/docs"]
    }
  }
}

Три сервера: Google Trends для аналитики, PostgreSQL для запросов к базе, файловая система для чтения документов за пределами проекта. Агент видит инструменты всех трёх и комбинирует их в одном запросе.

Пишем MCP-сервер для Google Trends

MCP-сервер на Python через библиотеку mcp:

from mcp.server.fastmcp import FastMCP
from pytrends.request import TrendReq
import json

mcp = FastMCP("google-trends")
pytrends = TrendReq(hl="ru", tz=180)  # русский язык, московское время

@mcp.tool()
def get_interest_over_time(query: str, timeframe: str = "today 3-m") -> str:
    """Получить динамику интереса к запросу за период.
    
    Аргументы:
        query: поисковый запрос (например 'machine learning')
        timeframe: период ('today 3-m', 'today 12-m', '2024-01-01 2024-12-31')
    
    Возвращает JSON с данными по неделям.
    """
    pytrends.build_payload([query], timeframe=timeframe)
    df = pytrends.interest_over_time()
    if df.empty:
        return json.dumps({"error": f"Нет данных для '{query}'"})
    
    # Убираем колонку isPartial, она мешает анализу
    if "isPartial" in df.columns:
        df = df.drop(columns=["isPartial"])
    
    return df.to_json(date_format="iso")

@mcp.tool()
def get_related_queries(query: str) -> str:
    """Получить связанные запросы: топ (самые частые) и растущие (с наибольшим ростом).
    
    Аргументы:
        query: поисковый запрос
    
    Растущие запросы с пометкой 'Breakout' выросли более чем на 5000%.
    """
    pytrends.build_payload([query], timeframe="today 3-m")
    related = pytrends.related_queries()
    
    result = {}
    for key in related:
        rising = related[key].get("rising")
        top = related[key].get("top")
        result[key] = {
            "rising": rising.to_dict() if rising is not None else {},
            "top": top.to_dict() if top is not None else {},
        }
    return json.dumps(result, ensure_ascii=False, default=str)

@mcp.tool()
def compare_queries(queries: list[str], timeframe: str = "today 3-m") -> str:
    """Сравнить до 5 запросов по динамике интереса.
    
    Аргументы:
        queries: список запросов для сравнения (максимум 5)
        timeframe: период
    
    Значения нормализованы: 100 = пик интереса, остальные относительно него.
    """
    if len(queries) > 5:
        return json.dumps({"error": "Максимум 5 запросов"})
    
    pytrends.build_payload(queries, timeframe=timeframe)
    df = pytrends.interest_over_time()
    
    if "isPartial" in df.columns:
        df = df.drop(columns=["isPartial"])
    
    return df.to_json(date_format="iso")

@mcp.tool()
def get_trending_searches(country: str = "russia") -> str:
    """Получить сегодняшние трендовые поисковые запросы в стране.
    
    Аргументы:
        country: страна ('russia', 'united_states', 'germany')
    """
    trending = pytrends.trending_searches(pn=country)
    return trending.to_json(force_ascii=False)

if __name__ == "__main__":
    mcp.run(transport="stdio")

Четыре инструмента: динамика интереса, связанные запросы, сравнение, трендовые запросы дня. Docstring каждого инструмента подробный — Cursor показывает его агенту как описание, и чем точнее описание, тем лучше агент понимает, когда какой инструмент вызвать.

Устанавливаем:

pip install mcp pytrends

Прописываем в .cursor/mcp.json, перезапускаем Cursor. Пишем в чат: «Проанализируй тренды по "AI coding assistant", найди растущие запросы и сравни топ-3 между собой». Cursor сам вызовет get_interest_over_time, потом get_related_queries, выберет три самых растущих, вызовет compare_queries и выдаст анализ. Один промпт, три вызова инструментов, ноль копирования.

MCP-сервер для своей базы данных

Допустим, у вас PostgreSQL с метриками продукта. Можно использовать готовый @modelcontextprotocol/server-postgres, а можно написать свой с контролем над тем, какие запросы допустимы:

from mcp.server.fastmcp import FastMCP
import asyncpg
import json

mcp = FastMCP("product-metrics")

DB_URL = "postgresql://readonly:pass@localhost:5432/analytics"

@mcp.tool()
async def get_daily_signups(days: int = 30) -> str:
    """Получить количество регистраций по дням за последние N дней."""
    conn = await asyncpg.connect(DB_URL)
    try:
        rows = await conn.fetch("""
            SELECT date_trunc('day', created_at) as day, count(*) as signups
            FROM users
            WHERE created_at > now() - interval '$1 days'
            GROUP BY 1 ORDER BY 1
        """, days)
        return json.dumps([{"day": str(r["day"].date()), "signups": r["signups"]} for r in rows])
    finally:
        await conn.close()

@mcp.tool()
async def get_feature_usage(feature_name: str, days: int = 7) -> str:
    """Получить статистику использования фичи: DAU, количество событий, среднее на пользователя."""
    conn = await asyncpg.connect(DB_URL)
    try:
        rows = await conn.fetch("""
            SELECT 
                date_trunc('day', timestamp) as day,
                count(distinct user_id) as dau,
                count(*) as events,
                round(count(*)::numeric / nullif(count(distinct user_id), 0), 1) as avg_per_user
            FROM events
            WHERE feature = $1 AND timestamp > now() - interval '$2 days'
            GROUP BY 1 ORDER BY 1
        """, feature_name, days)
        return json.dumps([dict(r) for r in rows], default=str)
    finally:
        await conn.close()

@mcp.tool()
async def get_retention(cohort_month: str) -> str:
    """Получить retention когорты по месяцам. cohort_month в формате '2026-01'."""
    conn = await asyncpg.connect(DB_URL)
    try:
        rows = await conn.fetch("""
            SELECT 
                months_since_signup,
                count(distinct user_id) as active_users,
                round(100.0 * count(distinct user_id) / 
                    first_value(count(distinct user_id)) over (order by months_since_signup), 1) as retention_pct
            FROM user_activity_monthly
            WHERE cohort = $1
            GROUP BY 1 ORDER BY 1
        """, cohort_month)
        return json.dumps([dict(r) for r in rows], default=str)
    finally:
        await conn.close()

if __name__ == "__main__":
    mcp.run(transport="stdio")

Подключение через read-only пользователя БД — агент может читать, но не может менять данные. В конфигурации:

{
  "mcpServers": {
    "product-metrics": {
      "command": "python",
      "args": ["-m", "metrics_server"],
      "env": {
        "DATABASE_URL": "postgresql://readonly:pass@localhost:5432/analytics"
      }
    }
  }
}

Теперь в Cursor можно писать: «Покажи retention январской когорты и сравни с использованием фичи onboarding за последний месяц». Агент вызовет get_retention("2026-01") и get_feature_usage("onboarding", 30), получит данные и проанализирует корреляцию.

Связка с LangGraph: многошаговый агент

Cursor с MCP хорош для разовых запросов. LangGraph описывает граф, где каждый узел может вызывать инструменты. MCP-инструменты подключаются через ToolNode:

from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool

# Инструменты (те же, что в MCP-сервере, но как LangChain tools)
@tool
def get_trends(query: str) -> str:
    """Получить данные Google Trends."""
    pytrends.build_payload([query], timeframe="today 3-m")
    return pytrends.interest_over_time().to_json()

@tool
def get_related(query: str) -> str:
    """Получить связанные запросы."""
    pytrends.build_payload([query], timeframe="today 3-m")
    related = pytrends.related_queries()
    rising = related[query].get("rising")
    return rising.to_json() if rising is not None else "{}"

@tool
def compare(queries: list[str]) -> str:
    """Сравнить до 5 запросов."""
    pytrends.build_payload(queries[:5], timeframe="today 3-m")
    return pytrends.interest_over_time().to_json()

tools = [get_trends, get_related, compare]

# Состояние графа
class State(TypedDict):
    messages: list
    iteration: int

# LLM с инструментами
llm = ChatAnthropic(model="claude-sonnet-4-20250514").bind_tools(tools)

def analyst(state: State) -> dict:
    """Узел-аналитик: решает, какой инструмент вызвать."""
    response = llm.invoke(state["messages"])
    return {"messages": state["messages"] + [response]}

def should_continue(state: State) -> str:
    """Условное ребро: есть ли вызовы инструментов?"""
    last = state["messages"][-1]
    if hasattr(last, "tool_calls") and last.tool_calls:
        return "tools"
    return "end"

# Сборка графа
workflow = StateGraph(State)
workflow.add_node("analyst", analyst)
workflow.add_node("tools", ToolNode(tools))

workflow.add_edge(START, "analyst")
workflow.add_conditional_edges("analyst", should_continue, {"tools": "tools", "end": END})
workflow.add_edge("tools", "analyst")  # после вызова инструмента — обратно к аналитику

agent = workflow.compile()

# Запуск
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "Найди растущие темы в области 'AI coding' и сравни топ-3"
    }],
    "iteration": 0,
})

Граф работает в цикле: аналитик решает, какой инструмент вызвать, ToolNode вызывает, результат возвращается аналитику, он решает, нужно ли ещё, и так пока не будет достаточно данных для ответа.

Три уровня использования одних и тех же инструментов. Cursor с MCP для быстрых вопросов в чате. LangGraph с теми же инструментами для многошаговых сценариев. Cursor как IDE для разработки и отладки самого агента.


MCP не делает агента умнее, он делает его полезнее. Модель та же, но вместо работы в вакууме она получает доступ к реальным данным: трендам, метрикам, базе, документам. Написать свой MCP-сервер — дело на пару часов, а эффект ощутимый: один промпт вместо пяти минут копирования данных из разных источников. Если добавить сверху LangGraph, получается агент, который не просто отвечает на вопрос, а проводит многошаговый анализ и сам решает, когда копнуть глубже.

Если у вас есть чем поделиться, пишите в комментариях.

В продолжение темы сегодня вечером, 6 мая в 20:00, пройдет бесплатный открытый урок на тему «LangGraph + MCP в Cursor IDE: создаем автономного агента для глубокого анализа Google Trends».

На занятии разберем, как связать LangGraph, MCP и Cursor IDE в одном прикладном сценарии: от подключения инструментов до агента, который ищет аномалии в Google Trends, сравнивает запросы и помогает находить темы с быстрым ростом интереса. Заодно можно будет посмотреть на формат обучения, познакомиться с экспертом курса «Разработка ИИ-агентов» Артёмом Ревой и задать вопросы. Записаться на урок.

Полный список бесплатных уроков мая смотрите в дайджесте.