Skip to main content
Glama
Akakinad

GraphRAG TypeScript MCP Tools

by Akakinad

GraphRAG TypeScript MCP Tools

Una implementación completa de un servidor MCP de GraphRAG construido con TypeScript, Neo4j y el SDK de MCP para TypeScript. Este proyecto demuestra cómo construir servidores MCP de calidad para producción que exponen herramientas basadas en grafos, recursos y características avanzadas como el muestreo de LLM y el autocompletado.

Construido como parte del curso Neo4j GraphAcademy — Building GraphRAG TypeScript MCP tools.


¿Qué es MCP?

El Model Context Protocol (MCP) es un estándar abierto de Anthropic que permite a los agentes de IA (Claude, Cursor, VS Code Copilot) conectarse a herramientas externas y fuentes de datos de manera estandarizada.


Estructura del proyecto

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


Lo que se construyó

Paso 1 — Primer servidor MCP (strawberry/index.ts)

El servidor MCP más simple posible. Una sola herramienta, sin base de datos, transporte 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),
  }],
}));

Resultado de la prueba: countLetters("strawberry", "r")3

Probado con el MCP Inspector, una herramienta basada en navegador para explorar y probar servidores MCP.


Paso 2 — Conexión a Neo4j (Ámbito de Módulo)

A diferencia del administrador de contexto lifespan de Python, TypeScript utiliza variables de ámbito de módulo: el driver se crea una vez al principio del archivo y se comparte directamente con todas las herramientas.

// 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";

Apagado elegante mediante SIGINT:

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

Paso 3 — Herramienta 1: graphStatistics

Cuenta todos los nodos y relaciones en Neo4j.

Resultado: {"nodes": 28863, "relationships": 332522}


Paso 4 — Herramienta 2: getMoviesByGenre

Busca películas por género ordenadas por la calificación de IMDB. Usa console.error() para el registro — nunca uses console.log() en servidores stdio (corrompe el canal 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 }
  );
  ...
});

Paso 5 — Herramienta 3: browse_movies_by_genre (Paginada)

Paginación basada en cursor usando SKIP y LIMIT de Neo4j:

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

Devuelve:

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

Paso 6 — Recurso: movie://{tmdbId}

Expone los detalles completos de la película por ID de TMDB usando 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
  }
);

Ejemplos: movie://603 (The Matrix), movie://13 (Forrest Gump)


Paso 7 — Avanzado: Muestreo (explainMovieData)

Herramientas que llaman al LLM durante la ejecución para convertir los datos brutos de Neo4j en lenguaje natural:

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

Sin muestreo: {'title': 'Toy Story', 'released': '1995', 'actors': [...]}

Con muestreo (VS Code Copilot): "Toy Story — Una aventura animada inteligente y divertida sobre Woody, un muñeco vaquero celoso que se siente desplazado cuando Buzz Lightyear se convierte en el nuevo favorito..."

Nota: Se requiere configurar la capacidad en el servidor de bajo nivel:

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

Paso 8 — Avanzado: Autocompletado

Sugerencias de autocompletado en tiempo real para los parámetros de género — consulta Neo4j mientras el usuario escribe:

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: [] } };
});

Diferencias clave con la versión de Python

Concepto

Python (FastMCP)

TypeScript (McpServer)

Registro de herramientas

decorador @mcp.tool()

método server.registerTool()

Estado compartido

Administrador de contexto lifespan

Variables de ámbito de módulo

Acceso al driver

ctx.request_context.lifespan_context.driver

driver (directo)

Registro

await ctx.info()

console.error()

Muestreo

ctx.session.create_message()

server.server.createMessage()

Autocompletado

@server.completion()

server.server.setRequestHandler(CompleteRequestSchema)

Estructura de archivos

Archivos separados por funcionalidad

Todo en un único index.ts

Parámetros numéricos

Anotaciones de tipo int de Python

Se necesita el envoltorio neo4j.int()

Parámetros de prompt

int, str, float

Siempre z.string(), parsear manualmente


Configuración

Requisitos previos

  • Node.js 20+

  • npm

  • Neo4j Sandbox — Conjunto de datos de recomendaciones de sandbox.neo4j.com

Instalar

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

Configurar credenciales

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

Verificar la configuración

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

Ejecución

Probar con MCP Inspector (interfaz de navegador)

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

Abre la URL mostrada en la terminal → Conectar → pestaña Herramientas → Listar herramientas → selecciona una herramienta → Ejecutar herramienta.

Ejecutar el servidor para uso con editores de IA

cd server
npx tsx index.ts

Configuración de VS Code (.vscode/mcp.json)

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

Probar en VS Code Copilot

Explica la película "Toy Story" usando la herramienta MCP movies-ts Busca películas de acción usando la herramienta MCP movies-ts Obtén estadísticas del grafo usando la herramienta MCP movies-ts


Curso

Ruta de aprendizaje: Generative AI & GraphRAG

Curso: Building GraphRAG TypeScript MCP tools


Building GraphRAG TypeScript MCP Tools

Repositorio complementario para el curso de GraphAcademy Building GraphRAG TypeScript MCP Tools.

Los estudiantes construyen un servidor MCP (Model Context Protocol) que se conecta a una base de datos de grafos Neo4j, exponiendo herramientas y recursos para su uso con asistentes de IA.

Primeros pasos

  1. Copia .env.example a .env y actualiza los valores con los detalles de conexión de tu instancia de Neo4j.

  2. Instala las dependencias:

npm install
  1. Inicia el servidor:

npm start
  1. Inspecciona el servidor con el MCP Inspector:

npm run inspect

Soluciones

El directorio solutions/ contiene el código completo para cada hito de la lección.

-
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