Skip to main content
Glama
Akakinad

GraphRAG TypeScript MCP Tools

by Akakinad

GraphRAG TypeScript MCP Tools

Полная реализация MCP-сервера GraphRAG, созданного с использованием TypeScript, Neo4j и MCP TypeScript SDK. Этот проект демонстрирует, как создавать MCP-серверы производственного уровня, которые предоставляют инструменты и ресурсы на основе графов, а также расширенные возможности, такие как семплирование LLM и автодополнение.

Создан в рамках курса Neo4j GraphAcademy — Building GraphRAG TypeScript MCP tools.


Что такое MCP?

Model Context Protocol (MCP) — это открытый стандарт от Anthropic, который позволяет AI-агентам (Claude, Cursor, VS Code Copilot) подключаться к внешним инструментам и источникам данных стандартизированным способом.


Структура проекта

genai-mcp-build-custom-tools-typescript/ ├── server/ │ └── index.ts ← Main MCP server: 4 tools + 1 resource + sampling + completions ├── strawberry/ │ └── index.ts ← First MCP server: simple countLetters tool ├── solutions/ ← Course reference solutions ├── .vscode/ │ └── mcp.json ← VS Code MCP configuration └── README.md


Что было создано

Шаг 1 — Первый MCP-сервер (strawberry/index.ts)

Простейший из возможных MCP-серверов. Один инструмент, без базы данных, stdio-транспорт.

server.registerTool("countLetters", {
  description: "Count occurrences of a letter in the text",
  inputSchema: {
    text: z.string().describe("The text to search in"),
    search: z.string().describe("The letter to count"),
  },
}, async ({ text, search }) => ({
  content: [{
    type: "text",
    text: String(text.toLowerCase().split(search.toLowerCase()).length - 1),
  }],
}));

Результат теста: countLetters("strawberry", "r")3

Протестировано с помощью MCP Inspector — браузерного инструмента для изучения и тестирования MCP-серверов.


Шаг 2 — Подключение к Neo4j (на уровне модуля)

В отличие от lifespan-менеджера контекста в Python, TypeScript использует переменные уровня модуля — драйвер создаётся один раз в верхней части файла и напрямую используется всеми инструментами.

// Created ONCE when file loads — shared by all tools
const driver: Driver = neo4j.driver(
  process.env["NEO4J_URI"] ?? "neo4j://localhost:7687",
  neo4j.auth.basic(
    process.env["NEO4J_USERNAME"] ?? "neo4j",
    process.env["NEO4J_PASSWORD"] ?? "password"
  )
);
const database = process.env["NEO4J_DATABASE"] ?? "neo4j";

Плавное завершение работы через SIGINT:

process.on("SIGINT", async () => {
  await driver.close();
  await server.close();
  process.exit(0);
});

Шаг 3 — Инструмент 1: graphStatistics

Подсчитывает все узлы и связи в Neo4j.

Результат: {"nodes": 28863, "relationships": 332522}


Шаг 4 — Инструмент 2: getMoviesByGenre

Ищет фильмы по жанру, отсортированные по рейтингу IMDB. Для логирования использует console.error() — никогда не используйте console.log() в stdio-серверах (это нарушает JSON-RPC-канал).

server.registerTool("getMoviesByGenre", {
  description: "Get movies by genre from the Neo4j database",
  inputSchema: {
    genre: z.string().describe("The genre to search for (e.g., Action, Comedy, Drama)"),
    limit: z.number().default(10).describe("Maximum number of movies to return"),
  },
}, async ({ genre, limit }) => {
  const { records } = await driver.executeQuery(query,
    { genre, limit: neo4j.int(limit) },  // neo4j.int() for 64-bit integer compatibility
    { database }
  );
  ...
});

Шаг 5 — Инструмент 3: browse_movies_by_genre (с пагинацией)

Курсорная пагинация на основе операторов Neo4j SKIP и LIMIT:

const skip = parseInt(cursor, 10) || 0;
// Cypher: SKIP $skip LIMIT $limit
const nextCursor = movies.length === pageSize ? String(skip + pageSize) : null;

Возвращает:

{
  "genre": "Action",
  "movies": [...],
  "nextCursor": "2",
  "page": 1,
  "pageSize": 2,
  "hasMore": true,
  "count": 2
}

Шаг 6 — Ресурс: movie://{tmdbId}

Предоставляет полные сведения о фильме по TMDB ID с использованием ResourceTemplate:

server.registerResource(
  "movie",
  new ResourceTemplate("movie://{tmdbId}", { list: undefined }),
  { description: "Get detailed information about a specific movie", mimeType: "application/json" },
  async (uri, { tmdbId }) => {
    // uri.href = "movie://603"
    // returns: contents array with JSON movie data
  }
);

Примеры: movie://603 (The Matrix), movie://13 (Forrest Gump)


Шаг 7 — Продвинутый уровень: семплирование (explainMovieData)

Инструменты, которые вызывают LLM во время выполнения для преобразования необработанных данных Neo4j в естественный язык:

const result = await server.server.createMessage({
  messages: [{
    role: "user",
    content: {
      type: "text",
      text: `Describe '${movieData.title}' (${movieData.released})...`,
    },
  }],
  maxTokens: 200,
});

Без семплирования: {'title': 'Toy Story', 'released': '1995', 'actors': [...]}

С семплированием (VS Code Copilot): «История игрушек» — умное, забавное анимационное приключение о Вуди, ревнивом кукле-ковбое, который чувствует себя вытесненным, когда Базз Лайтер становится новым любимцем...

Примечание: требуется установка capability на низкоуровневом сервере:

server.server["_capabilities"] = { ...server.server["_capabilities"], completions: {} };

Шаг 8 — Продвинутый уровень: автодополнение

Подсказки автодополнения в реальном времени для параметров жанра — выполняет запросы к Neo4j по мере ввода пользователем:

import { CompleteRequestSchema } from "@modelcontextprotocol/sdk/types.js";

server.server.setRequestHandler(CompleteRequestSchema, async (request) => {
  if (request.params.argument.name === "genre") {
    const { records } = await driver.executeQuery(
      `MATCH (g:Genre)
       WHERE g.name STARTS WITH $prefix
       RETURN g.name AS name
       ORDER BY name ASC LIMIT 10`,
      { prefix: request.params.argument.value },
      { database }
    );
    return { completion: { values: records.map(r => r.get("name")) } };
  }
  return { completion: { values: [] } };
});

Ключевые отличия от Python-версии

Понятие

Python (FastMCP)

TypeScript (McpServer)

Регистрация инструмента

декоратор @mcp.tool()

метод server.registerTool()

Общее состояние

Менеджер контекста lifespan

Переменные уровня модуля

Доступ к драйверу

ctx.request_context.lifespan_context.driver

driver (напрямую)

Логирование

await ctx.info()

console.error()

Семплирование

ctx.session.create_message()

server.server.createMessage()

Автодополнение

@server.completion()

server.server.setRequestHandler(CompleteRequestSchema)

Структура файлов

Отдельные файлы для каждой функции

Всё в одном index.ts

Числовые параметры

Подсказки типов Python int

требуется обёртка neo4j.int()

Параметры промпта

int, str, float

Всегда z.string(), разбирать вручную


Настройка

Предварительные требования

  • Node.js 20+

  • npm

  • Neo4j Sandbox — набор данных Recommendations от sandbox.neo4j.com

Установка

git clone https://github.com/Akakinad/genai-mcp-build-custom-tools-typescript
cd genai-mcp-build-custom-tools-typescript
npm install

Настройка учётных данных

cat > server/.env << EOF
NEO4J_URI=bolt://your-sandbox-ip:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=your-password
NEO4J_DATABASE=neo4j
EOF

Проверка настройки

npx tsx client/test_environment.ts
# Expected: All checks passed!

Запуск

Тестирование с помощью MCP Inspector (браузерный интерфейс)

cd server
npx @modelcontextprotocol/inspector npx tsx index.ts

Откройте URL, показанный в терминале → Connect → вкладка Tools → List Tools → выберите инструмент → Run Tool.

Запуск сервера для использования в AI-редакторе

cd server
npx tsx index.ts

Конфигурация VS Code (.vscode/mcp.json)

{
  "servers": {
    "movies-ts": {
      "type": "stdio",
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/server/index.ts"]
    }
  }
}

Тестирование в VS Code Copilot

Объясните фильм «История игрушек» с помощью MCP-инструмента movies-ts Найдите боевики с помощью MCP-инструмента movies-ts Получите статистику графа с помощью MCP-инструмента movies-ts


Курс

Учебный путь: Generative AI & GraphRAG

Курс: Building GraphRAG TypeScript MCP tools


Building GraphRAG TypeScript MCP Tools

Сопутствующий репозиторий для курса GraphAcademy Building GraphRAG TypeScript MCP Tools.

Студенты создают MCP-сервер (Model Context Protocol), который подключается к графовой базе данных Neo4j и предоставляет инструменты и ресурсы для использования с AI-ассистентами.

Начало работы

  1. Скопируйте .env.example в .env и обновите значения, указав данные подключения к Neo4j.

  2. Установите зависимости:

npm install
  1. Запустите сервер:

npm start
  1. Проверьте сервер с помощью MCP Inspector:

npm run inspect

Решения

Каталог solutions/ содержит готовый код для каждой контрольной точки урока.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP server for AI dialogue using various LLM models via AceDataCloud

  • MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2

  • Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Akakinad/genai-mcp-build-custom-tools-typescript'

If you have feedback or need assistance with the MCP directory API, please join our Discord server