@mgsoftwarebv/mg-dashboard-mcp 7.0.8 → 7.0.9

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.
package/dist/index.js CHANGED
@@ -6759,6 +6759,7 @@ var apiKey = getArg2("api-key") || process.env.MG_DASHBOARD_API_KEY;
6759
6759
  var sshKeyPath = getArg2("ssh-key") || process.env.MG_DASHBOARD_SSH_KEY;
6760
6760
  var databaseUrl = getArg2("database-url") || process.env.DATABASE_PRIMARY_POOLER_URL || process.env.DATABASE_PRIMARY_URL;
6761
6761
  var encryptionKey = getArg2("encryption-key") || process.env.ENCRYPTION_KEY;
6762
+ var dashboardBaseUrl = (getArg2("dashboard-url") || process.env.MG_DASHBOARD_BASE_URL || "https://dashboard.mgsoftware.nl").replace(/\/$/, "");
6762
6763
  var mijnhostApiKey = getArg2("mijnhost-api-key") || process.env.MIJNHOST_API_KEY;
6763
6764
  function isMijnhostViaSshProxyEnabled() {
6764
6765
  const arg = getArg2("mijnhost-via-ssh-proxy");
@@ -10790,6 +10791,34 @@ var TOOLS = [
10790
10791
  required: ["action", "domain", "type", "name"]
10791
10792
  }
10792
10793
  },
10794
+ // ----- Team memory -----
10795
+ {
10796
+ name: "search-team-memory",
10797
+ description: "Search the team's ENTIRE past Cursor history (every developer, every project) for how something was handled before. Use this FIRST, before investigating from scratch, whenever you: hit a non-trivial bug or error, are about to build something that may have been done before, need a project-specific convention/gotcha, or the user asks 'have we done X', 'how did we fix Y', or 'did we solve this already'. Hybrid semantic + keyword search over mirrored conversations. Returns ranked past chats with repo, date, a solution snippet and a similarity score. Phrase the query as the problem in natural language (e.g. 'release pipeline PM2 deploy fails with module not found').",
10798
+ inputSchema: {
10799
+ type: "object",
10800
+ properties: {
10801
+ query: {
10802
+ type: "string",
10803
+ description: "The problem/topic in natural language. Include error text, tool/module names, or symptoms for best recall."
10804
+ },
10805
+ repo: {
10806
+ type: "string",
10807
+ description: "Optional repo filter, e.g. 'github.com/MGSoftwareBV/mg-dashboard'. Omit to search across all projects."
10808
+ },
10809
+ scope: {
10810
+ type: "string",
10811
+ enum: ["team", "mine"],
10812
+ description: "'team' (default) searches everyone's history; 'mine' restricts to the calling user's own conversations."
10813
+ },
10814
+ limit: {
10815
+ type: "number",
10816
+ description: "Max results to return (1-25, default 8)."
10817
+ }
10818
+ },
10819
+ required: ["query"]
10820
+ }
10821
+ },
10793
10822
  // ----- Trigger.dev -----
10794
10823
  ...TRIGGER_TOOLS
10795
10824
  ];
@@ -10861,6 +10890,65 @@ async function executeToolCall(name, a, _serverId) {
10861
10890
  const ctx = authContext;
10862
10891
  try {
10863
10892
  switch (name) {
10893
+ // ----- Team memory -----
10894
+ case "search-team-memory": {
10895
+ const query = typeof a.query === "string" ? a.query.trim() : "";
10896
+ if (!query) {
10897
+ return { content: [{ type: "text", text: "Error: query is required" }] };
10898
+ }
10899
+ const res = await fetch(`${dashboardBaseUrl}/api/team-memory/search`, {
10900
+ method: "POST",
10901
+ headers: {
10902
+ "content-type": "application/json",
10903
+ authorization: `Bearer ${apiKey}`
10904
+ },
10905
+ body: JSON.stringify({
10906
+ query,
10907
+ repo: typeof a.repo === "string" ? a.repo : void 0,
10908
+ scope: a.scope === "mine" ? "mine" : "team",
10909
+ limit: typeof a.limit === "number" ? a.limit : void 0
10910
+ })
10911
+ });
10912
+ if (!res.ok) {
10913
+ const detail = await res.text().catch(() => "");
10914
+ return {
10915
+ content: [
10916
+ {
10917
+ type: "text",
10918
+ text: `Error: team-memory search failed (${res.status}). ${detail.slice(0, 300)}`
10919
+ }
10920
+ ]
10921
+ };
10922
+ }
10923
+ const data = await res.json();
10924
+ if (data.count === 0) {
10925
+ return {
10926
+ content: [
10927
+ {
10928
+ type: "text",
10929
+ text: `No prior team conversations matched "${query}". Proceed from scratch.`
10930
+ }
10931
+ ]
10932
+ };
10933
+ }
10934
+ const lines = data.hits.map((hit, index5) => {
10935
+ const when = hit.lastMessageAt ? new Date(hit.lastMessageAt).toISOString().slice(0, 10) : "unknown date";
10936
+ const repo = hit.repo ?? "unknown repo";
10937
+ const sim = hit.similarity !== null ? ` \xB7 ${(hit.similarity * 100).toFixed(0)}% match` : "";
10938
+ return `${index5 + 1}. [${repo} \xB7 ${when}${sim}] ${hit.title}
10939
+ ${(hit.summary ?? hit.snippet).replace(/\s+/g, " ").slice(0, 500)}`;
10940
+ });
10941
+ return {
10942
+ content: [
10943
+ {
10944
+ type: "text",
10945
+ text: `Found ${data.count} prior conversation(s) (${data.mode} search) \u2014 reuse this before solving from scratch:
10946
+
10947
+ ` + lines.join("\n\n")
10948
+ }
10949
+ ]
10950
+ };
10951
+ }
10864
10952
  // ----- Servers -----
10865
10953
  case "list-servers": {
10866
10954
  const data = ctx.allowedServerIds !== null ? await db.execute(sql`