@memly/mcp-server 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +73 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -19967,7 +19967,7 @@ class MemlyClient {
19967
19967
  }
19968
19968
 
19969
19969
  // src/tools.ts
19970
- function registerTools(server, client) {
19970
+ function registerTools(server, client, projectId) {
19971
19971
  server.tool("load_context", [
19972
19972
  "ALWAYS call this tool FIRST, before responding to any message in a new conversation.",
19973
19973
  "It loads your persistent memory from previous sessions so you can provide accurate, context-aware assistance.",
@@ -19977,7 +19977,7 @@ function registerTools(server, client) {
19977
19977
  }, async ({ topic }) => {
19978
19978
  try {
19979
19979
  const query = topic ?? "recent technical decisions architecture patterns current work";
19980
- const result = await client.searchMemories(query, undefined, 20);
19980
+ const result = await client.searchMemories(query, projectId, 20);
19981
19981
  if (result.is_cold_start || result.memories.length === 0) {
19982
19982
  return {
19983
19983
  content: [{
@@ -20045,9 +20045,9 @@ Then answer normally. Use the memories above to inform your response.`
20045
20045
  };
20046
20046
  }
20047
20047
  });
20048
- server.tool("search_memories", "Search your stored memories semantically. Call this when you need to recall a specific previous decision, code pattern, or technical context that may not have been loaded by load_context.", {
20048
+ server.tool("search_memories", "Search your stored memories semantically across ALL projects (cross-project by default). Call this when you need to recall a specific previous decision, code pattern, or technical context. Pass project_id to scope to a specific project.", {
20049
20049
  query: exports_external.string().min(1).describe("What to search for (natural language)"),
20050
- project_id: exports_external.string().uuid().optional().describe("Limit search to a specific project"),
20050
+ project_id: exports_external.string().uuid().optional().describe("Scope to a specific project UUID. Omit to search across all projects."),
20051
20051
  limit: exports_external.number().int().min(1).max(20).optional().describe("Max results (default: 5)")
20052
20052
  }, async ({ query, project_id, limit }) => {
20053
20053
  try {
@@ -20085,7 +20085,7 @@ ${formatted}`
20085
20085
  project_id: exports_external.string().uuid().optional().describe("Associate with a specific project")
20086
20086
  }, async ({ content, project_id }) => {
20087
20087
  try {
20088
- await client.saveMemory(content, project_id, "user");
20088
+ await client.saveMemory(content, project_id ?? projectId, "user");
20089
20089
  return {
20090
20090
  content: [{
20091
20091
  type: "text",
@@ -20561,6 +20561,27 @@ function writeClaudeDesktop() {
20561
20561
  };
20562
20562
  }
20563
20563
  }
20564
+ async function resolveProjectId(apiKey, projectRoot) {
20565
+ try {
20566
+ const pkgPath = join(projectRoot, "package.json");
20567
+ const fingerprint = existsSync(pkgPath) ? readFileSync(pkgPath, "utf-8").slice(0, 500) : `Project path: ${projectRoot}/src/index`;
20568
+ const controller = new AbortController;
20569
+ const timeout = setTimeout(() => controller.abort(), 8000);
20570
+ const res = await fetch("https://api.memly.site/v1/chat/completions", {
20571
+ method: "POST",
20572
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
20573
+ body: JSON.stringify({ model: "gpt-4.1-nano", stream: false, messages: [{ role: "user", content: fingerprint }] }),
20574
+ signal: controller.signal
20575
+ });
20576
+ clearTimeout(timeout);
20577
+ const id = res.headers.get("X-Memly-Project-Id");
20578
+ if (id && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id))
20579
+ return id;
20580
+ return null;
20581
+ } catch {
20582
+ return null;
20583
+ }
20584
+ }
20564
20585
  async function reportTelemetry(results) {
20565
20586
  try {
20566
20587
  const controller = new AbortController;
@@ -20667,6 +20688,34 @@ async function runInit() {
20667
20688
  try {
20668
20689
  writeFileSync(join(projectRoot, ".memly-initialized"), new Date().toISOString());
20669
20690
  } catch {}
20691
+ process.stdout.write(`
20692
+ Resolving project ID... `);
20693
+ const projectId = await resolveProjectId(apiKey, projectRoot);
20694
+ if (projectId) {
20695
+ try {
20696
+ writeFileSync(join(projectRoot, ".memly-project"), JSON.stringify({ project_id: projectId }, null, 2));
20697
+ console.log(`✓ ${projectId}`);
20698
+ const MARKER = `<!-- memly-project:${projectId} -->`;
20699
+ const ideFiles = [
20700
+ join(projectRoot, ".cursorrules"),
20701
+ join(projectRoot, ".github", "copilot-instructions.md"),
20702
+ join(projectRoot, ".clinerules"),
20703
+ join(projectRoot, ".windsurfrules")
20704
+ ];
20705
+ for (const f of ideFiles) {
20706
+ if (existsSync(f)) {
20707
+ const content = readFileSync(f, "utf-8");
20708
+ if (!content.includes(MARKER)) {
20709
+ writeFileSync(f, content.trimEnd() + `
20710
+ ` + MARKER + `
20711
+ `);
20712
+ }
20713
+ }
20714
+ }
20715
+ } catch {}
20716
+ } else {
20717
+ console.log("⊘ skipped (proxy unreachable — run init again after connecting)");
20718
+ }
20670
20719
  await reportTelemetry(results);
20671
20720
  console.log(`
20672
20721
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -20683,6 +20732,8 @@ async function runInit() {
20683
20732
  }
20684
20733
 
20685
20734
  // src/index.ts
20735
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
20736
+ import { join as join2 } from "node:path";
20686
20737
  var apiKey = process.env.MEMLY_API_KEY;
20687
20738
  if (process.argv.includes("--init") || process.argv.includes("init")) {
20688
20739
  await runInit();
@@ -20696,6 +20747,21 @@ if (!apiKey) {
20696
20747
  var apiUrl = process.env.MEMLY_API_URL ?? "https://api.memly.site";
20697
20748
  var client = new MemlyClient(apiUrl, apiKey);
20698
20749
  var isHttp = process.argv.includes("--http");
20750
+ function readProjectId() {
20751
+ if (process.env.MEMLY_PROJECT_ID)
20752
+ return process.env.MEMLY_PROJECT_ID;
20753
+ try {
20754
+ const file = join2(process.cwd(), ".memly-project");
20755
+ if (existsSync2(file)) {
20756
+ const data = JSON.parse(readFileSync2(file, "utf-8"));
20757
+ if (data.project_id && /^[0-9a-f-]{36}$/i.test(data.project_id)) {
20758
+ return data.project_id;
20759
+ }
20760
+ }
20761
+ } catch {}
20762
+ return;
20763
+ }
20764
+ var projectId = readProjectId();
20699
20765
  if (isHttp) {
20700
20766
  const port = Number(process.env.MEMLY_PORT ?? 3800);
20701
20767
  const httpServer = Bun.serve({
@@ -20707,7 +20773,7 @@ if (isHttp) {
20707
20773
  }
20708
20774
  if (url.pathname === "/mcp") {
20709
20775
  const server = new McpServer({ name: "memly", version: "0.1.0" });
20710
- registerTools(server, client);
20776
+ registerTools(server, client, projectId);
20711
20777
  registerResources(server, client);
20712
20778
  registerPrompts(server, client);
20713
20779
  const transport = new WebStandardStreamableHTTPServerTransport({
@@ -20724,7 +20790,7 @@ if (isHttp) {
20724
20790
  console.log(` Health: http://localhost:${httpServer.port}/health`);
20725
20791
  } else {
20726
20792
  const server = new McpServer({ name: "memly", version: "0.1.0" });
20727
- registerTools(server, client);
20793
+ registerTools(server, client, projectId);
20728
20794
  registerResources(server, client);
20729
20795
  registerPrompts(server, client);
20730
20796
  const transport = new StdioServerTransport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memly/mcp-server",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Memly MCP Server — persistent memory for any IDE",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",