Skip to main content
Glama
server.js9.58 kB
/** * @file server.js * @description * Provides an MCP server implementation that registers knowledge graph management tools * (entities, relations, observations, graph reading, and search operations) using McpServer. * Each tool is documented with descriptive names and parameter schemas to be used by clients. */ import { z } from 'zod'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; /** * MCP server that exposes knowledge graph operations as tools for Claude or other agents. * @extends McpServer */ export class Server extends McpServer { /** * Instance of KnowledgeGraphManager that implements CRUD and search operations. * @private * @type {import('./knowledge-graph-manager').KnowledgeGraphManager} */ #knowledgeGraphManager = null; /** * Constructs the Server and initializes the underlying MCP server. * @param {{ name: string, version: string }} serverInfo * Information about this server (name and version) for registration. * @param {import('./knowledge-graph-manager').KnowledgeGraphManager} knowledgeGraphManager * The manager instance to delegate entity, observation, and relation commands. */ constructor(serverInfo, knowledgeGraphManager) { super(serverInfo); this.#knowledgeGraphManager = knowledgeGraphManager; this.#createTools(); } /** * Registers all MCP tools related to knowledge graph management. * Each tool is described with a name, human-readable description, parameter schema, * and handler function that returns MCP-compatible content. * @private */ #createTools() { // Tool: create_entities this.tool( 'create_entities', 'Create entities in the knowledge graph. Inserts each entity if not exists and optionally seeds it with observations.', { entities: z.array(z.object({ name: z.string().describe('Unique name of the entity.'), entityType: z.string().describe('Type or category of the entity.'), observations: z.array(z.string()).optional() .describe('Initial list of observations to attach to the entity.') })).describe('Array of entities to create.') }, async ({ entities }) => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.createEntities(entities), null, 2 ) }] }) ); // Tool: create_relations this.tool( 'create_relations', 'Create directed relations between entities. Skips existing relations.', { relations: z.array(z.object({ from: z.string().describe('Source entity name.'), to: z.string().describe('Target entity name.'), relationType: z.string().describe('Label or type of the relation.') })).describe('Array of relations to create.') }, async ({ relations }) => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.createRelations(relations), null, 2 ) }] }) ); // Tool: add_observations this.tool( 'add_observations', 'Add text observations to existing entities and index them for full-text and semantic search.', { observations: z.array(z.object({ entityName: z.string().describe('Name of the entity to annotate.'), contents: z.array(z.string()).describe('List of text observations to add.') })).describe('List of {entityName, contents} pairs.') }, async ({ observations }) => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.addObservations(observations), null, 2 ) }] }) ); // Tool: delete_entities this.tool( 'delete_entities', 'Delete entities (and cascaded observations/relations) by their names.', { entityNames: z.array(z.string()).describe('Names of entities to delete.') }, async ({ entityNames }) => { await this.#knowledgeGraphManager.deleteEntities(entityNames); return { content: [{ type: 'text', text: 'Entities deleted' }] }; } ); // Tool: delete_relations this.tool( 'delete_relations', 'Remove specified relations between entities without deleting the entities themselves.', { relations: z.array(z.object({ from: z.string().describe('Source entity name.'), to: z.string().describe('Target entity name.'), relationType: z.string().describe('Type of the relation to remove.') })).describe('Array of relations to delete.') }, async ({ relations }) => { await this.#knowledgeGraphManager.deleteRelations(relations); return { content: [{ type: 'text', text: 'Relations deleted' }] }; } ); // Tool: delete_observations this.tool( 'delete_observations', 'Remove specific observations from entities by matching text.', { deletions: z.array(z.object({ entityName: z.string().describe('Name of the entity.'), observations: z.array(z.string()).describe('Exact observation texts to delete.') })).describe('List of {entityName, observations} deletion requests.') }, async ({ deletions }) => { await this.#knowledgeGraphManager.deleteObservations(deletions); return { content: [{ type: 'text', text: 'Observations deleted' }] }; } ); // Tool: read_graph this.tool( 'read_graph', 'Retrieve the entire knowledge graph: all entities with their observations and relations.', {}, async () => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.readGraph(), null, 2 ) }] }) ); // Tool: search_nodes this.tool( 'search_nodes', 'Search for entities and relations by semantic similarity.', { query: z.string().describe('Search query string.'), topK: z.number().int().min(1).max(100) .optional() .default(8) .describe('Max number of results to return.'), threshold: z.number().min(0).max(1) .optional() .default(0.35) .describe('Distance threshold for semantic filtering.') }, async (args) => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.searchNodes(args), null, 2 ) }] }) ); // Tool: open_nodes this.tool( 'open_nodes', 'Expand specified entities: return their full details including observations and relations.', { names: z.array(z.string()).describe('Names of entities to expand.') }, async ({ names }) => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.openNodes(names), null, 2 ) }] }) ); // Tool: set_importance this.tool( 'set_importance', 'Set the importance level for an entity (critical, important, normal, temporary, deprecated).', { entityName: z.string().describe('Name of the entity.'), importance: z.enum(['critical', 'important', 'normal', 'temporary', 'deprecated']) .describe('Importance level for the entity.') }, async ({ entityName, importance }) => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.setImportance(entityName, importance), null, 2 ) }] }) ); } }

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/iAchilles/memento'

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