aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-03 05:05:54 -0800
committerFuwn <[email protected]>2026-02-03 19:34:35 -0800
commitc1aed3e7582a7f17e324280d0f0bc0cd91119870 (patch)
tree35c191be352ef25b3a54f3931efecfb4187671e7
parenttest(sdk): Add in-memory store tests (diff)
downloadarchived-imemio-c1aed3e7582a7f17e324280d0f0bc0cd91119870.tar.xz
archived-imemio-c1aed3e7582a7f17e324280d0f0bc0cd91119870.zip
feat(mcp): Scaffold MCP server with memory tools
-rw-r--r--packages/mcp/package.json33
-rw-r--r--packages/mcp/src/index.ts193
-rw-r--r--packages/mcp/tsconfig.json21
3 files changed, 247 insertions, 0 deletions
diff --git a/packages/mcp/package.json b/packages/mcp/package.json
new file mode 100644
index 0000000..f45d98d
--- /dev/null
+++ b/packages/mcp/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "@imemio/mcp",
+ "version": "0.0.1",
+ "description": "MCP server for imemio AI agent memory service",
+ "type": "module",
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "bin": {
+ "imemio-mcp": "./dist/index.js"
+ },
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
+ }
+ },
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "build": "tsc",
+ "dev": "tsc --watch"
+ },
+ "dependencies": {
+ "@imemio/sdk": "workspace:*",
+ "@modelcontextprotocol/sdk": "^1.0.0",
+ "zod": "^3.24.0"
+ },
+ "devDependencies": {
+ "@types/node": "^22.13.3",
+ "typescript": "^5.7.3"
+ }
+}
diff --git a/packages/mcp/src/index.ts b/packages/mcp/src/index.ts
new file mode 100644
index 0000000..18c61ce
--- /dev/null
+++ b/packages/mcp/src/index.ts
@@ -0,0 +1,193 @@
+#!/usr/bin/env node
+
+import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
+import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
+import { z } from "zod";
+import { InMemoryStore } from "@imemio/sdk";
+
+const store = new InMemoryStore();
+const tagSchema = z.object({
+ id: z.string(),
+ name: z.string(),
+});
+const metadataSchema = z.record(z.unknown());
+const server = new McpServer({
+ name: "imemio",
+ version: "0.0.1",
+});
+
+server.tool(
+ "create_memory",
+ "Create a new memory",
+ {
+ content: z.string().describe("The content of the memory"),
+ projectId: z.string().describe("The project ID this memory belongs to"),
+ folderId: z.string().optional().describe("Optional folder ID"),
+ tags: z.array(tagSchema).optional().describe("Optional tags"),
+ metadata: metadataSchema.optional().describe("Optional metadata"),
+ },
+ async (parameters) => {
+ const memory = await store.create({
+ content: parameters.content,
+ projectId: parameters.projectId,
+ folderId: parameters.folderId,
+ tags: parameters.tags,
+ metadata: parameters.metadata,
+ });
+
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: JSON.stringify(memory, null, 2),
+ },
+ ],
+ };
+ },
+);
+
+server.tool(
+ "get_memory",
+ "Get a memory by ID",
+ {
+ id: z.string().describe("The memory ID"),
+ },
+ async (parameters) => {
+ const result = await store.read(parameters.id);
+
+ if (!result.success) {
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: `Memory not found: ${parameters.id}`,
+ },
+ ],
+ isError: true,
+ };
+ }
+
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: JSON.stringify(result.value, null, 2),
+ },
+ ],
+ };
+ },
+);
+
+server.tool(
+ "update_memory",
+ "Update an existing memory",
+ {
+ id: z.string().describe("The memory ID to update"),
+ content: z.string().optional().describe("New content"),
+ folderId: z.string().nullable().optional().describe("New folder ID"),
+ tags: z.array(tagSchema).optional().describe("New tags"),
+ metadata: metadataSchema.optional().describe("New metadata"),
+ },
+ async (parameters) => {
+ const result = await store.update(parameters.id, {
+ content: parameters.content,
+ folderId: parameters.folderId,
+ tags: parameters.tags,
+ metadata: parameters.metadata,
+ });
+
+ if (!result.success) {
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: `Memory not found: ${parameters.id}`,
+ },
+ ],
+ isError: true,
+ };
+ }
+
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: JSON.stringify(result.value, null, 2),
+ },
+ ],
+ };
+ },
+);
+
+server.tool(
+ "delete_memory",
+ "Delete a memory",
+ {
+ id: z.string().describe("The memory ID to delete"),
+ },
+ async (parameters) => {
+ const result = await store.delete(parameters.id);
+
+ if (!result.success) {
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: `Memory not found: ${parameters.id}`,
+ },
+ ],
+ isError: true,
+ };
+ }
+
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: `Memory deleted: ${parameters.id}`,
+ },
+ ],
+ };
+ },
+);
+
+server.tool(
+ "list_memories",
+ "List memories with optional filters",
+ {
+ projectId: z.string().optional().describe("Filter by project ID"),
+ folderId: z.string().optional().describe("Filter by folder ID"),
+ tags: z.array(z.string()).optional().describe("Filter by tag IDs"),
+ },
+ async (parameters) => {
+ const filter =
+ parameters.projectId || parameters.folderId || parameters.tags
+ ? {
+ projectId: parameters.projectId,
+ folderId: parameters.folderId,
+ tags: parameters.tags,
+ }
+ : undefined;
+ const memories = await store.list(filter);
+
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: JSON.stringify(memories, null, 2),
+ },
+ ],
+ };
+ },
+);
+
+async function main(): Promise<void> {
+ const transport = new StdioServerTransport();
+
+ await server.connect(transport);
+}
+
+main().catch((error) => {
+ console.error("Server error:", error);
+ process.exit(1);
+});
diff --git a/packages/mcp/tsconfig.json b/packages/mcp/tsconfig.json
new file mode 100644
index 0000000..a55afed
--- /dev/null
+++ b/packages/mcp/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "lib": ["ES2022"],
+ "strict": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "noUncheckedIndexedAccess": true,
+ "noEmitOnError": true
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist"]
+}