@chamba/mcp 0.3.0 → 0.3.2

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/main.js +72 -19
  2. package/package.json +3 -3
package/dist/main.js CHANGED
@@ -585,6 +585,58 @@ function registerSummarizeToVault(server, logger, services) {
585
585
  );
586
586
  }
587
587
 
588
+ // src/tools/vault-status.ts
589
+ import { listVaultNotes, ObsidianDetector as ObsidianDetector3 } from "@chamba/core";
590
+ var TOOL_NAME13 = "chamba_vault_status";
591
+ var DESCRIPTION13 = "Diagnose the Obsidian vault connection: the resolved vault path, whether it was found, and the markdown notes chamba can actually see (the same set `chamba_load_context` searches). Use this to confirm the vault points at the vault root (the folder containing `.obsidian`), not at `.obsidian` itself.";
592
+ var MAX_LISTED = 50;
593
+ function registerVaultStatus(server, logger, services) {
594
+ server.registerTool(
595
+ TOOL_NAME13,
596
+ {
597
+ title: "Vault status",
598
+ description: DESCRIPTION13,
599
+ inputSchema: {}
600
+ },
601
+ async () => {
602
+ const detection = await new ObsidianDetector3(services.fs).detect({
603
+ explicitPath: services.obsidianVaultPath,
604
+ searchRoots: obsidianSearchRoots(services)
605
+ });
606
+ if (!detection.found || !detection.path) {
607
+ const text2 = `No Obsidian vault found.
608
+ Set CHAMBA_OBSIDIAN_VAULT_PATH to your vault root (the folder containing .obsidian), or place the vault under a common location. Searched: ${obsidianSearchRoots(services).join(", ")}.`;
609
+ logger.info({ tool: TOOL_NAME13, found: false }, "vault-status");
610
+ return {
611
+ content: [{ type: "text", text: text2 }],
612
+ structuredContent: { found: false }
613
+ };
614
+ }
615
+ const paths = await listVaultNotes(services.fs, detection.path);
616
+ const names = paths.map((p) => p.slice(detection.path?.length ?? 0).replace(/^\/+/, ""));
617
+ const source = services.obsidianVaultPath ? "CHAMBA_OBSIDIAN_VAULT_PATH" : "autodetected";
618
+ logger.info({ tool: TOOL_NAME13, vault: detection.path, notes: names.length }, "vault-status");
619
+ const shown = names.slice(0, MAX_LISTED);
620
+ const more = names.length > MAX_LISTED ? `
621
+ \u2026and ${names.length - MAX_LISTED} more` : "";
622
+ const text = `Vault: ${detection.path} (${source})
623
+ Notes chamba can see: ${names.length}
624
+
625
+ ${shown.map((n) => `- ${n}`).join("\n")}${more}` + (names.length === 0 ? "\n\n\u26A0\uFE0F No notes found. If your path ends in `.obsidian`, point it at the parent folder instead." : "");
626
+ return {
627
+ content: [{ type: "text", text }],
628
+ structuredContent: {
629
+ found: true,
630
+ vaultPath: detection.path,
631
+ source,
632
+ noteCount: names.length,
633
+ notes: shown
634
+ }
635
+ };
636
+ }
637
+ );
638
+ }
639
+
588
640
  // src/tools/workspace-init.ts
589
641
  import {
590
642
  joinPath as joinPath4,
@@ -594,14 +646,14 @@ import {
594
646
  WorkspaceScanner as WorkspaceScanner4
595
647
  } from "@chamba/core";
596
648
  import { z as z12 } from "zod";
597
- var TOOL_NAME13 = "chamba_workspace_init";
598
- var DESCRIPTION13 = "Scan the workspace and generate `.chamba/workspace.md` (description, languages, framework, conventions, active projects, folder map). Respects .gitignore/.dockerignore and never reads node_modules or binaries. If the file already exists it is NOT overwritten \u2014 its current contents are returned so the model/user decides what to do.";
649
+ var TOOL_NAME14 = "chamba_workspace_init";
650
+ var DESCRIPTION14 = "Scan the workspace and generate `.chamba/workspace.md` (description, languages, framework, conventions, active projects, folder map). Respects .gitignore/.dockerignore and never reads node_modules or binaries. If the file already exists it is NOT overwritten \u2014 its current contents are returned so the model/user decides what to do.";
599
651
  function registerWorkspaceInit(server, logger, services) {
600
652
  server.registerTool(
601
- TOOL_NAME13,
653
+ TOOL_NAME14,
602
654
  {
603
655
  title: "Init workspace",
604
- description: DESCRIPTION13,
656
+ description: DESCRIPTION14,
605
657
  inputSchema: {
606
658
  root: z12.string().optional().describe("Workspace root to scan. Defaults to the directory chamba runs in.")
607
659
  }
@@ -611,7 +663,7 @@ function registerWorkspaceInit(server, logger, services) {
611
663
  const wsPath = joinPath4(workspaceRoot, WORKSPACE_RELATIVE_PATH);
612
664
  if (await services.fs.exists(wsPath)) {
613
665
  const currentContents = await services.fs.readFile(wsPath);
614
- logger.info({ tool: TOOL_NAME13, wsPath }, "workspace.md already exists, not overwriting");
666
+ logger.info({ tool: TOOL_NAME14, wsPath }, "workspace.md already exists, not overwriting");
615
667
  return {
616
668
  content: [
617
669
  {
@@ -631,7 +683,7 @@ ${currentContents}`
631
683
  await services.fs.mkdir(joinPath4(workspaceRoot, WORKSPACE_DIR4));
632
684
  await services.fs.writeFile(wsPath, markdown);
633
685
  logger.info(
634
- { tool: TOOL_NAME13, wsPath, projects: workspace.projects.length },
686
+ { tool: TOOL_NAME14, wsPath, projects: workspace.projects.length },
635
687
  "workspace.md created"
636
688
  );
637
689
  return {
@@ -657,20 +709,20 @@ import {
657
709
  WORKSPACE_RELATIVE_PATH as WORKSPACE_RELATIVE_PATH2,
658
710
  WorkspaceScanner as WorkspaceScanner5
659
711
  } from "@chamba/core";
660
- var TOOL_NAME14 = "chamba_workspace_reload";
661
- var DESCRIPTION14 = "Re-scan the workspace and return a diff against the current `.chamba/workspace.md`. NEVER overwrites the file \u2014 the user may have hand-edited it. The model decides whether to apply changes.";
712
+ var TOOL_NAME15 = "chamba_workspace_reload";
713
+ var DESCRIPTION15 = "Re-scan the workspace and return a diff against the current `.chamba/workspace.md`. NEVER overwrites the file \u2014 the user may have hand-edited it. The model decides whether to apply changes.";
662
714
  function registerWorkspaceReload(server, logger, services) {
663
715
  server.registerTool(
664
- TOOL_NAME14,
716
+ TOOL_NAME15,
665
717
  {
666
718
  title: "Reload workspace",
667
- description: DESCRIPTION14,
719
+ description: DESCRIPTION15,
668
720
  inputSchema: {}
669
721
  },
670
722
  async () => {
671
723
  const wsPath = joinPath5(services.cwd, WORKSPACE_RELATIVE_PATH2);
672
724
  if (!await services.fs.exists(wsPath)) {
673
- logger.info({ tool: TOOL_NAME14, wsPath }, "no workspace.md to reload");
725
+ logger.info({ tool: TOOL_NAME15, wsPath }, "no workspace.md to reload");
674
726
  return {
675
727
  content: [
676
728
  {
@@ -684,7 +736,7 @@ function registerWorkspaceReload(server, logger, services) {
684
736
  const scanner = new WorkspaceScanner5(services.fs);
685
737
  const rescanned = renderWorkspaceMarkdown2(await scanner.scan(services.cwd));
686
738
  if (textsEqual(current, rescanned)) {
687
- logger.info({ tool: TOOL_NAME14, wsPath }, "workspace.md up to date");
739
+ logger.info({ tool: TOOL_NAME15, wsPath }, "workspace.md up to date");
688
740
  return {
689
741
  content: [
690
742
  {
@@ -694,7 +746,7 @@ function registerWorkspaceReload(server, logger, services) {
694
746
  ]
695
747
  };
696
748
  }
697
- logger.info({ tool: TOOL_NAME14, wsPath }, "workspace.md differs from re-scan");
749
+ logger.info({ tool: TOOL_NAME15, wsPath }, "workspace.md differs from re-scan");
698
750
  return {
699
751
  content: [
700
752
  {
@@ -713,24 +765,24 @@ ${diffLines(current, rescanned)}
713
765
 
714
766
  // src/tools/workspace-show.ts
715
767
  import { joinPath as joinPath6, WORKSPACE_RELATIVE_PATH as WORKSPACE_RELATIVE_PATH3 } from "@chamba/core";
716
- var TOOL_NAME15 = "chamba_workspace_show";
717
- var DESCRIPTION15 = "Show the current workspace map. Reads `.chamba/workspace.md` from the workspace root and returns its contents. If no workspace file exists yet, says so \u2014 the model can then run chamba_workspace_init to create one.";
768
+ var TOOL_NAME16 = "chamba_workspace_show";
769
+ var DESCRIPTION16 = "Show the current workspace map. Reads `.chamba/workspace.md` from the workspace root and returns its contents. If no workspace file exists yet, says so \u2014 the model can then run chamba_workspace_init to create one.";
718
770
  function registerWorkspaceShow(server, logger, services) {
719
771
  server.registerTool(
720
- TOOL_NAME15,
772
+ TOOL_NAME16,
721
773
  {
722
774
  title: "Show workspace",
723
- description: DESCRIPTION15,
775
+ description: DESCRIPTION16,
724
776
  inputSchema: {}
725
777
  },
726
778
  async () => {
727
779
  const path = joinPath6(services.cwd, WORKSPACE_RELATIVE_PATH3);
728
780
  try {
729
781
  const contents = await services.fs.readFile(path);
730
- logger.info({ tool: TOOL_NAME15, path }, "workspace.md read");
782
+ logger.info({ tool: TOOL_NAME16, path }, "workspace.md read");
731
783
  return { content: [{ type: "text", text: contents }] };
732
784
  } catch {
733
- logger.info({ tool: TOOL_NAME15, path }, "no workspace.md found");
785
+ logger.info({ tool: TOOL_NAME16, path }, "no workspace.md found");
734
786
  return {
735
787
  content: [
736
788
  {
@@ -754,6 +806,7 @@ function createServer(logger, services = createNodeServices()) {
754
806
  registerWorkspaceReload(server, logger, services);
755
807
  registerLoadContext(server, logger, services);
756
808
  registerSummarizeToVault(server, logger, services);
809
+ registerVaultStatus(server, logger, services);
757
810
  registerGeneratePlan(server, logger, services);
758
811
  registerReviewPlan(server, logger, services);
759
812
  registerCreateWorktree(server, logger, services);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chamba/mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "chamba MCP server — orchestration, workspace, worktree and Obsidian tools for any MCP-capable editor",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -36,8 +36,8 @@
36
36
  "@modelcontextprotocol/sdk": "^1.12.0",
37
37
  "pino": "^9.0.0",
38
38
  "zod": "^3.23.0",
39
- "@chamba/adapters": "0.3.0",
40
- "@chamba/core": "0.3.0"
39
+ "@chamba/adapters": "0.3.2",
40
+ "@chamba/core": "0.3.2"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.0.0",