aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMaheshtheDev <[email protected]>2026-01-17 00:57:48 +0000
committerMaheshtheDev <[email protected]>2026-01-17 00:57:48 +0000
commitacdb4226350b93047dea590cadcb2e72a37471d5 (patch)
tree8529ad6891c531577f1e90a428ec027b041adc8c /apps
parentfix: mintlify build (#677) (diff)
downloadsupermemory-acdb4226350b93047dea590cadcb2e72a37471d5.tar.xz
supermemory-acdb4226350b93047dea590cadcb2e72a37471d5.zip
add (mcp): projects aware tool on every init (#676)01-16-add_mcp_projects_aware_tool_on_every_init
Diffstat (limited to 'apps')
-rw-r--r--apps/mcp/package.json4
-rw-r--r--apps/mcp/src/index.ts5
-rw-r--r--apps/mcp/src/server.ts88
3 files changed, 89 insertions, 8 deletions
diff --git a/apps/mcp/package.json b/apps/mcp/package.json
index a0042da6..5ba472ad 100644
--- a/apps/mcp/package.json
+++ b/apps/mcp/package.json
@@ -9,8 +9,8 @@
},
"dependencies": {
"@cloudflare/workers-oauth-provider": "^0.2.2",
- "@modelcontextprotocol/sdk": "^1.12.1",
- "agents": "^0.2.32",
+ "@modelcontextprotocol/sdk": "^1.25.2",
+ "agents": "^0.3.5",
"hono": "^4.11.1",
"posthog-node": "^5.18.0",
"supermemory": "^4.0.0",
diff --git a/apps/mcp/src/index.ts b/apps/mcp/src/index.ts
index a1fe7bac..0586492f 100644
--- a/apps/mcp/src/index.ts
+++ b/apps/mcp/src/index.ts
@@ -1,8 +1,9 @@
-import { Hono } from "hono"
import { cors } from "hono/cors"
+import { Hono } from "hono"
import { SupermemoryMCP } from "./server"
import { isApiKey, validateApiKey, validateOAuthToken } from "./auth"
import { initPosthog } from "./posthog"
+import type { ContentfulStatusCode } from "hono/utils/http-status"
type Bindings = {
MCP_SERVER: DurableObjectNamespace
@@ -78,7 +79,7 @@ app.get("/.well-known/oauth-authorization-server", async (c) => {
if (!response.ok) {
return c.json(
{ error: "Failed to fetch authorization server metadata" },
- response.status,
+ { status: response.status as ContentfulStatusCode },
)
}
diff --git a/apps/mcp/src/server.ts b/apps/mcp/src/server.ts
index bbcd493e..d83d2326 100644
--- a/apps/mcp/src/server.ts
+++ b/apps/mcp/src/server.ts
@@ -20,6 +20,7 @@ type Props = {
export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
private clientInfo: { name: string; version?: string } | null = null
+ private cachedContainerTags: string[] = []
server = new McpServer({
name: "supermemory",
@@ -37,7 +38,6 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
initPosthog(this.env.POSTHOG_API_KEY)
-
// Hook MCP McpAgent to capture client info
this.server.server.oninitialized = async () => {
const clientVersion = this.server.server.getClientVersion()
@@ -49,6 +49,11 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
await this.ctx.storage.put("clientInfo", this.clientInfo)
}
}
+
+ await this.refreshContainerTags() // Fetch available projects for schema descriptions
+
+ const containerTagDescription = this.getContainerTagDescription()
+
const memorySchema = z.object({
content: z
.string()
@@ -58,7 +63,7 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
containerTag: z
.string()
.max(128, "Container tag exceeds maximum length")
- .describe("Optional container tag")
+ .describe(containerTagDescription)
.optional(),
})
@@ -71,7 +76,7 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
containerTag: z
.string()
.max(128, "Container tag exceeds maximum length")
- .describe("Optional container tag")
+ .describe(containerTagDescription)
.optional(),
})
@@ -79,7 +84,7 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
containerTag: z
.string()
.max(128, "Container tag exceeds maximum length")
- .describe("Optional container tag to scope the profile")
+ .describe(containerTagDescription)
.optional(),
includeRecent: z
.boolean()
@@ -176,6 +181,63 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
},
)
+ // Register listProjects tool
+ this.server.registerTool(
+ "listProjects",
+ {
+ description:
+ "List all available projects for organizing memories. Use this to discover valid project names for memory/recall operations.",
+ inputSchema: z.object({
+ refresh: z
+ .boolean()
+ .optional()
+ .default(true)
+ .describe("Refresh the list from the server (default: true)"),
+ }),
+ },
+ // @ts-expect-error - zod type inference issue with MCP SDK
+ async (args: { refresh?: boolean }) => {
+ try {
+ if (args.refresh !== false) {
+ await this.refreshContainerTags()
+ }
+ const projects = this.cachedContainerTags
+
+ if (projects.length === 0) {
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: "No projects found. Memories will use the default project.",
+ },
+ ],
+ }
+ }
+
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: `Available projects:\n${projects.map((p) => `- ${p}`).join("\n")}`,
+ },
+ ],
+ }
+ } catch (error) {
+ const message =
+ error instanceof Error ? error.message : "An unexpected error occurred"
+ return {
+ content: [
+ {
+ type: "text" as const,
+ text: `Error listing projects: ${message}`,
+ },
+ ],
+ isError: true,
+ }
+ }
+ },
+ )
+
// Register whoAmI tool
this.server.registerTool(
"whoAmI",
@@ -222,6 +284,7 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
"User profile and preferences for system context injection. Returns a formatted system message with user's stable preferences and recent activity.",
//argsSchema: contextPromptSchema.shape, TODO: commenting out for now as it will add more friction to the user
},
+ // @ts-expect-error - zod type inference issue with MCP SDK
async (args: ContextPromptArgs) => {
try {
const { containerTag, includeRecent = true } = args
@@ -543,4 +606,21 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
private getMcpSessionId(): string {
return this.ctx.id.name || "unknown"
}
+
+ private async refreshContainerTags(): Promise<void> {
+ try {
+ const client = this.getClient()
+ this.cachedContainerTags = await client.getProjects()
+ } catch (error) {
+ console.error("Failed to fetch container tags:", error)
+ }
+ }
+
+ private getContainerTagDescription(): string {
+ const baseDescription = "Optional project to scope memories"
+ if (this.cachedContainerTags.length === 0) {
+ return baseDescription
+ }
+ return `${baseDescription}. Available projects: ${this.cachedContainerTags.join(", ")}`
+ }
}