From 9cbea339af6938f6cf08d5d2a58bdd1a41278771 Mon Sep 17 00:00:00 2001 From: Barry Zhang Date: Tue, 19 Nov 2024 16:06:36 -0500 Subject: [PATCH 1/7] claude memory --- src/memory/index.ts | 414 +++++++++++++++++++++++++++++++++++++++ src/memory/package.json | 28 +++ src/memory/tsconfig.json | 11 ++ 3 files changed, 453 insertions(+) create mode 100644 src/memory/index.ts create mode 100644 src/memory/package.json create mode 100644 src/memory/tsconfig.json diff --git a/src/memory/index.ts b/src/memory/index.ts new file mode 100644 index 00000000..37546cd7 --- /dev/null +++ b/src/memory/index.ts @@ -0,0 +1,414 @@ +#!/usr/bin/env node + +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { + CallToolRequestSchema, + ListToolsRequestSchema, +} from "@modelcontextprotocol/sdk/types.js"; +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + + +// Define the path to the JSONL file, you can change this to your desired local path +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const MEMORY_FILE_PATH = path.join(__dirname, 'memory.json'); + +// We are storing our memory using entities, relations, and observations in a graph structure +interface Entity { + name: string; + entityType: string; + observations: string[]; +} + +interface Relation { + from: string; + to: string; + relationType: string; +} + +interface KnowledgeGraph { + entities: Entity[]; + relations: Relation[]; +} + +// The KnowledgeGraphManager class contains all operations to interact with the knowledge graph +class KnowledgeGraphManager { + private async loadGraph(): Promise { + try { + const data = await fs.readFile(MEMORY_FILE_PATH, "utf-8"); + const lines = data.split("\n").filter(line => line.trim() !== ""); + return lines.reduce((graph: KnowledgeGraph, line) => { + const item = JSON.parse(line); + if (item.type === "entity") graph.entities.push(item as Entity); + if (item.type === "relation") graph.relations.push(item as Relation); + return graph; + }, { entities: [], relations: [] }); + } catch (error) { + if (error instanceof Error && 'code' in error && (error as any).code === "ENOENT") { + return { entities: [], relations: [] }; + } + throw error; + } + } + + private async saveGraph(graph: KnowledgeGraph): Promise { + const lines = [ + ...graph.entities.map(e => JSON.stringify({ type: "entity", ...e })), + ...graph.relations.map(r => JSON.stringify({ type: "relation", ...r })), + ]; + await fs.writeFile(MEMORY_FILE_PATH, lines.join("\n")); + } + + async createEntities(entities: Entity[]): Promise { + const graph = await this.loadGraph(); + const newEntities = entities.filter(e => !graph.entities.some(existingEntity => existingEntity.name === e.name)); + graph.entities.push(...newEntities); + await this.saveGraph(graph); + return newEntities; + } + + async createRelations(relations: Relation[]): Promise { + const graph = await this.loadGraph(); + const newRelations = relations.filter(r => !graph.relations.some(existingRelation => + existingRelation.from === r.from && + existingRelation.to === r.to && + existingRelation.relationType === r.relationType + )); + graph.relations.push(...newRelations); + await this.saveGraph(graph); + return newRelations; + } + + async addObservations(observations: { entityName: string; contents: string[] }[]): Promise<{ entityName: string; addedObservations: string[] }[]> { + const graph = await this.loadGraph(); + const results = observations.map(o => { + const entity = graph.entities.find(e => e.name === o.entityName); + if (!entity) { + throw new Error(`Entity with name ${o.entityName} not found`); + } + const newObservations = o.contents.filter(content => !entity.observations.includes(content)); + entity.observations.push(...newObservations); + return { entityName: o.entityName, addedObservations: newObservations }; + }); + await this.saveGraph(graph); + return results; + } + + async deleteEntities(entityNames: string[]): Promise { + const graph = await this.loadGraph(); + graph.entities = graph.entities.filter(e => !entityNames.includes(e.name)); + graph.relations = graph.relations.filter(r => !entityNames.includes(r.from) && !entityNames.includes(r.to)); + await this.saveGraph(graph); + } + + async deleteObservations(deletions: { entityName: string; observations: string[] }[]): Promise { + const graph = await this.loadGraph(); + deletions.forEach(d => { + const entity = graph.entities.find(e => e.name === d.entityName); + if (entity) { + entity.observations = entity.observations.filter(o => !d.observations.includes(o)); + } + }); + await this.saveGraph(graph); + } + + async deleteRelations(relations: Relation[]): Promise { + const graph = await this.loadGraph(); + graph.relations = graph.relations.filter(r => !relations.some(delRelation => + r.from === delRelation.from && + r.to === delRelation.to && + r.relationType === delRelation.relationType + )); + await this.saveGraph(graph); + } + + async readGraph(): Promise { + return this.loadGraph(); + } + + // Very basic search function + async searchNodes(query: string): Promise { + const graph = await this.loadGraph(); + + // Filter entities + const filteredEntities = graph.entities.filter(e => + e.name.toLowerCase().includes(query.toLowerCase()) || + e.entityType.toLowerCase().includes(query.toLowerCase()) || + e.observations.some(o => o.toLowerCase().includes(query.toLowerCase())) + ); + + // Create a Set of filtered entity names for quick lookup + const filteredEntityNames = new Set(filteredEntities.map(e => e.name)); + + // Filter relations to only include those between filtered entities + const filteredRelations = graph.relations.filter(r => + filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to) + ); + + const filteredGraph: KnowledgeGraph = { + entities: filteredEntities, + relations: filteredRelations, + }; + + return filteredGraph; + } + + async openNodes(names: string[]): Promise { + const graph = await this.loadGraph(); + + // Filter entities + const filteredEntities = graph.entities.filter(e => names.includes(e.name)); + + // Create a Set of filtered entity names for quick lookup + const filteredEntityNames = new Set(filteredEntities.map(e => e.name)); + + // Filter relations to only include those between filtered entities + const filteredRelations = graph.relations.filter(r => + filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to) + ); + + const filteredGraph: KnowledgeGraph = { + entities: filteredEntities, + relations: filteredRelations, + }; + + return filteredGraph; + } +} + +const knowledgeGraphManager = new KnowledgeGraphManager(); + + +// The server instance and tools exposed to Claude +const server = new Server({ + name: "knowledge-graph-server", + version: "1.0.0", +}, { + capabilities: { + tools: {}, + }, + },); + +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { + tools: [ + { + name: "create_entities", + description: "Create multiple new entities in the knowledge graph", + inputSchema: { + type: "object", + properties: { + entities: { + type: "array", + items: { + type: "object", + properties: { + name: { type: "string", description: "The name of the entity" }, + entityType: { type: "string", description: "The type of the entity" }, + observations: { + type: "array", + items: { type: "string" }, + description: "An array of observation contents associated with the entity" + }, + }, + required: ["name", "entityType", "observations"], + }, + }, + }, + required: ["entities"], + }, + }, + { + name: "create_relations", + description: "Create multiple new relations between entities in the knowledge graph. Relations should be in active voice", + inputSchema: { + type: "object", + properties: { + relations: { + type: "array", + items: { + type: "object", + properties: { + from: { type: "string", description: "The name of the entity where the relation starts" }, + to: { type: "string", description: "The name of the entity where the relation ends" }, + relationType: { type: "string", description: "The type of the relation" }, + }, + required: ["from", "to", "relationType"], + }, + }, + }, + required: ["relations"], + }, + }, + { + name: "add_observations", + description: "Add new observations to existing entities in the knowledge graph", + inputSchema: { + type: "object", + properties: { + observations: { + type: "array", + items: { + type: "object", + properties: { + entityName: { type: "string", description: "The name of the entity to add the observations to" }, + contents: { + type: "array", + items: { type: "string" }, + description: "An array of observation contents to add" + }, + }, + required: ["entityName", "contents"], + }, + }, + }, + required: ["observations"], + }, + }, + { + name: "delete_entities", + description: "Delete multiple entities and their associated relations from the knowledge graph", + inputSchema: { + type: "object", + properties: { + entityNames: { + type: "array", + items: { type: "string" }, + description: "An array of entity names to delete" + }, + }, + required: ["entityNames"], + }, + }, + { + name: "delete_observations", + description: "Delete specific observations from entities in the knowledge graph", + inputSchema: { + type: "object", + properties: { + deletions: { + type: "array", + items: { + type: "object", + properties: { + entityName: { type: "string", description: "The name of the entity containing the observations" }, + observations: { + type: "array", + items: { type: "string" }, + description: "An array of observations to delete" + }, + }, + required: ["entityName", "observations"], + }, + }, + }, + required: ["deletions"], + }, + }, + { + name: "delete_relations", + description: "Delete multiple relations from the knowledge graph", + inputSchema: { + type: "object", + properties: { + relations: { + type: "array", + items: { + type: "object", + properties: { + from: { type: "string", description: "The name of the entity where the relation starts" }, + to: { type: "string", description: "The name of the entity where the relation ends" }, + relationType: { type: "string", description: "The type of the relation" }, + }, + required: ["from", "to", "relationType"], + }, + description: "An array of relations to delete" + }, + }, + required: ["relations"], + }, + }, + { + name: "read_graph", + description: "Read the entire knowledge graph", + inputSchema: { + type: "object", + properties: {}, + }, + }, + { + name: "search_nodes", + description: "Search for nodes in the knowledge graph based on a query", + inputSchema: { + type: "object", + properties: { + query: { type: "string", description: "The search query to match against entity names, types, and observation content" }, + }, + required: ["query"], + }, + }, + { + name: "open_nodes", + description: "Open specific nodes in the knowledge graph by their names", + inputSchema: { + type: "object", + properties: { + names: { + type: "array", + items: { type: "string" }, + description: "An array of entity names to retrieve", + }, + }, + required: ["names"], + }, + }, + ], + }; +}); + +server.setRequestHandler(CallToolRequestSchema, async (request) => { + const { name, arguments: args } = request.params; + + if (!args) { + throw new Error(`No arguments provided for tool: ${name}`); + } + + switch (name) { + case "create_entities": + return { toolResult: await knowledgeGraphManager.createEntities(args.entities as Entity[]) }; + case "create_relations": + return { toolResult: await knowledgeGraphManager.createRelations(args.relations as Relation[]) }; + case "add_observations": + return { toolResult: await knowledgeGraphManager.addObservations(args.observations as { entityName: string; contents: string[] }[]) }; + case "delete_entities": + await knowledgeGraphManager.deleteEntities(args.entityNames as string[]); + return { toolResult: "Entities deleted successfully" }; + case "delete_observations": + await knowledgeGraphManager.deleteObservations(args.deletions as { entityName: string; observations: string[] }[]); + return { toolResult: "Observations deleted successfully" }; + case "delete_relations": + await knowledgeGraphManager.deleteRelations(args.relations as Relation[]); + return { toolResult: "Relations deleted successfully" }; + case "read_graph": + return { toolResult: await knowledgeGraphManager.readGraph() }; + case "search_nodes": + return { toolResult: await knowledgeGraphManager.searchNodes(args.query as string) }; + case "open_nodes": + return { toolResult: await knowledgeGraphManager.openNodes(args.names as string[]) }; + default: + throw new Error(`Unknown tool: ${name}`); + } +}); + +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); + console.error("Knowledge Graph MCP Server running on stdio"); +} + +main().catch((error) => { + console.error("Fatal error in main():", error); + process.exit(1); +}); \ No newline at end of file diff --git a/src/memory/package.json b/src/memory/package.json new file mode 100644 index 00000000..8cb17d27 --- /dev/null +++ b/src/memory/package.json @@ -0,0 +1,28 @@ +{ + "name": "@modelcontextprotocol/server-memory", + "version": "0.1.0", + "description": "MCP server for enabling memory for Claude through a knowledge graph", + "license": "MIT", + "author": "Anthropic, PBC (https://anthropic.com)", + "homepage": "https://modelcontextprotocol.io", + "bugs": "https://github.com/modelcontextprotocol/servers/issues", + "type": "module", + "bin": { + "mcp-server-memory": "dist/index.js" + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsc && shx chmod +x dist/*.js", + "prepare": "npm run build", + "watch": "tsc --watch" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "0.5.0" + }, + "devDependencies": { + "shx": "^0.3.4", + "typescript": "^5.6.2" + } +} diff --git a/src/memory/tsconfig.json b/src/memory/tsconfig.json new file mode 100644 index 00000000..4d33cae1 --- /dev/null +++ b/src/memory/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "." + }, + "include": [ + "./**/*.ts" + ] + } + \ No newline at end of file From 700e2e72b4ed6e7d2616d082bf58c6e284f57f89 Mon Sep 17 00:00:00 2001 From: Barry Zhang Date: Tue, 19 Nov 2024 21:18:50 -0500 Subject: [PATCH 2/7] package.json --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 72ad23f4..39e83766 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@modelcontextprotocol/server-gdrive": "*", "@modelcontextprotocol/server-postgres": "*", "@modelcontextprotocol/server-puppeteer": "*", - "@modelcontextprotocol/server-slack": "*" + "@modelcontextprotocol/server-slack": "*", + "@modelcontextprotocol/server-memory": "*" } } From a8af9d2a30f3054d027cd6549f2a945296cca16b Mon Sep 17 00:00:00 2001 From: Barry Zhang Date: Tue, 19 Nov 2024 21:14:32 -0500 Subject: [PATCH 3/7] minor naming change --- src/memory/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory/index.ts b/src/memory/index.ts index 37546cd7..ad3937ce 100644 --- a/src/memory/index.ts +++ b/src/memory/index.ts @@ -183,7 +183,7 @@ const knowledgeGraphManager = new KnowledgeGraphManager(); // The server instance and tools exposed to Claude const server = new Server({ - name: "knowledge-graph-server", + name: "memory-server", version: "1.0.0", }, { capabilities: { From 66c3fa59a6aeae03b61415aa7a242ec362069419 Mon Sep 17 00:00:00 2001 From: Barry Zhang Date: Tue, 19 Nov 2024 21:31:53 -0500 Subject: [PATCH 4/7] readme --- src/memory/README.md | 99 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/memory/README.md diff --git a/src/memory/README.md b/src/memory/README.md new file mode 100644 index 00000000..af67de56 --- /dev/null +++ b/src/memory/README.md @@ -0,0 +1,99 @@ +# Knowledge Graph Memory Server +A basic MCP server implementation that provides persistent memory using a knowledge-graph. The server manages entities, their observations, and the relationships between them using a JSON-based file system. + +# Core Concepts + +## Entities +Entities are the primary nodes in the knowledge graph. Each entity has: +- A unique name (identifier) +- An entity type (e.g., "person", "organization", "event") +- A list of observations + +Example: +```json +{ + "name": "John_Smith", + "entityType": "person", + "observations": ["Lives in New York", "Works as a software engineer"] +} +``` + +## Relations +Relations define directed connections between entities. They are always stored in active voice and describe how entities interact or relate to each other. +Example: +```jsonCopy{ + "from": "John_Smith", + "to": "TechCorp", + "relationType": "works_at" +} +``` +## Observations +Observations are discrete pieces of information about an entity. They are: + +- Stored as strings +- Attached to specific entities +- Can be added or removed independently +- Should be atomic (one fact per observation) + +Example: +```jsonCopy{ + "entityName": "John_Smith", + "observations": [ + "Speaks fluent Spanish", + "Graduated in 2019", + "Prefers morning meetings" + ] +} +``` + +# Tools + +## Entity Management + +- create_entities: Create new entities in the knowledge graph with names, types, and observations +- delete_entities: Remove entities and their associated relations from the graph +- add_observations: Add new observations to existing entities +- delete_observations: Remove specific observations from entities + + +## Relation Management + +- create_relations: Establish relationships between entities in active voice +- delete_relations: Remove specific relationships between entities + + +## Query Tools + +- read_graph: Retrieve the entire knowledge graph +- search_nodes: Search for nodes based on names, types, and observation content +- open_nodes: Access specific nodes by their names + +# Prompts + +The prompt for utilizing memory depends on the use case, but here is an example prompt for chat personalization. You could use this prompt in the "Custom Instructions" field of a Project + +``` +Follow these steps for each interaction: + +1. User Identification: + - You should assume that you are interacting with default_user + - If you have not identified default_user, proactively try to do so. + +2. Memory Retrieval: + - Always begin your chat by saying only "Remembering..." and retrieve all relevant information from your knowledge graph + - Always refer to your knowledge as your "memory" + +3. Memory + - While conversing with the user, be attentive to any new information that falls into these categories: + a) Basic Identity (Age, gender, location, Job title, education level, etc.) + b) Behaviors (interests, habits, etc.) + c) Preferences (communication style, preferred language, etc.) + d) Goals/Psychology (Goals, targets, aspirations, etc.) + e) Relationships (personal and professional relationships up to 3 degrees of separation) + +4. Memory Update: + - If any new information was gathered during the interaction, update your memory as follows: + a) Create nodes for recurring organizations, people, and significant events, connecting them to the current node. + b) Store most facts as observations within these nodes + - Try to perform all updates in one operation using the create and delete functions. +``` \ No newline at end of file From 7b98f9f8b6a632084b22dba6bca36f474d9db361 Mon Sep 17 00:00:00 2001 From: Barry Zhang Date: Tue, 19 Nov 2024 21:40:03 -0500 Subject: [PATCH 5/7] rebase --- package-lock.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/package-lock.json b/package-lock.json index 977c234d..c8b9ecb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "dependencies": { "@modelcontextprotocol/server-everything": "*", "@modelcontextprotocol/server-gdrive": "*", + "@modelcontextprotocol/server-memory": "*", "@modelcontextprotocol/server-postgres": "*", "@modelcontextprotocol/server-puppeteer": "*", "@modelcontextprotocol/server-slack": "*" @@ -72,6 +73,10 @@ "resolved": "src/gdrive", "link": true }, + "node_modules/@modelcontextprotocol/server-memory": { + "resolved": "src/memory", + "link": true + }, "node_modules/@modelcontextprotocol/server-postgres": { "resolved": "src/postgres", "link": true @@ -2873,6 +2878,21 @@ "typescript": "^5.6.2" } }, + "src/memory": { + "name": "@modelcontextprotocol/server-memory", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/sdk": "0.5.0" + }, + "bin": { + "mcp-server-memory": "dist/index.js" + }, + "devDependencies": { + "shx": "^0.3.4", + "typescript": "^5.6.2" + } + }, "src/postgres": { "name": "@modelcontextprotocol/server-postgres", "version": "0.1.0", From cb575e2585d0fab000f629337eaf70e25a0b0ec7 Mon Sep 17 00:00:00 2001 From: Barry Zhang Date: Wed, 20 Nov 2024 10:25:05 -0500 Subject: [PATCH 6/7] adding comments --- src/memory/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/memory/README.md b/src/memory/README.md index af67de56..159374f2 100644 --- a/src/memory/README.md +++ b/src/memory/README.md @@ -1,6 +1,8 @@ # Knowledge Graph Memory Server A basic MCP server implementation that provides persistent memory using a knowledge-graph. The server manages entities, their observations, and the relationships between them using a JSON-based file system. +This lets Claude remember information about the user across chats and projects, and lets them bypass the issues of having super long chats + # Core Concepts ## Entities From 080e8dcceead1e919062073eabefe0400faebec9 Mon Sep 17 00:00:00 2001 From: Barry Zhang Date: Wed, 20 Nov 2024 10:33:08 -0500 Subject: [PATCH 7/7] rebase and rebuild --- package-lock.json | 86 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c8b9ecb9..a0a7a8ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,6 +73,10 @@ "resolved": "src/gdrive", "link": true }, + "node_modules/@modelcontextprotocol/server-google-maps": { + "resolved": "src/google-maps", + "link": true + }, "node_modules/@modelcontextprotocol/server-memory": { "resolved": "src/memory", "link": true @@ -195,11 +199,20 @@ "version": "22.9.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", - "devOptional": true, "dependencies": { "undici-types": "~6.19.8" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/pg": { "version": "8.11.10", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz", @@ -348,6 +361,12 @@ "node": ">=4" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/b4a": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", @@ -594,6 +613,18 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -702,6 +733,15 @@ "node": ">= 14" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -978,6 +1018,20 @@ "node": ">= 0.8" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2664,8 +2718,7 @@ "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "devOptional": true + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "node_modules/universalify": { "version": "2.0.1", @@ -2878,6 +2931,33 @@ "typescript": "^5.6.2" } }, + "src/google-maps": { + "name": "@modelcontextprotocol/server-google-maps", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/sdk": "0.6.0", + "@types/node-fetch": "^2.6.12" + }, + "bin": { + "mcp-server-google-maps": "dist/index.js" + }, + "devDependencies": { + "shx": "^0.3.4", + "typescript": "^5.6.2" + } + }, + "src/google-maps/node_modules/@modelcontextprotocol/sdk": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-0.6.0.tgz", + "integrity": "sha512-9rsDudGhDtMbvxohPoMMyAUOmEzQsOK+XFchh6gZGqo8sx9sBuZQs+CUttXqa8RZXKDaJRCN2tUtgGof7jRkkw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "raw-body": "^3.0.0", + "zod": "^3.23.8" + } + }, "src/memory": { "name": "@modelcontextprotocol/server-memory", "version": "0.1.0",