@chamba/mcp 0.5.2 → 0.6.1

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 +56 -34
  2. package/package.json +3 -3
package/dist/main.js CHANGED
@@ -1,4 +1,6 @@
1
1
  // src/main.ts
2
+ import { readFileSync } from "fs";
3
+ import { fileURLToPath } from "url";
2
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
5
 
4
6
  // src/logging.ts
@@ -646,14 +648,17 @@ ${shown.map((n) => `- ${n}`).join("\n")}${more}` + (names.length === 0 ? "\n\n\u
646
648
  // src/tools/workspace-init.ts
647
649
  import {
648
650
  joinPath as joinPath4,
651
+ ObsidianDetector as ObsidianDetector4,
649
652
  renderWorkspaceMarkdown,
653
+ VAULT_OVERVIEW_FILE,
654
+ VaultInitializer,
650
655
  WORKSPACE_DIR as WORKSPACE_DIR4,
651
656
  WORKSPACE_RELATIVE_PATH,
652
657
  WorkspaceScanner as WorkspaceScanner4
653
658
  } from "@chamba/core";
654
659
  import { z as z12 } from "zod";
655
660
  var TOOL_NAME14 = "chamba_workspace_init";
656
- 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.";
661
+ 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. When no Obsidian vault is available, it also bootstraps one at the workspace root and seeds a "Workspace overview" note (disable with createVault: false).';
657
662
  function registerWorkspaceInit(server, logger, services) {
658
663
  server.registerTool(
659
664
  TOOL_NAME14,
@@ -661,47 +666,49 @@ function registerWorkspaceInit(server, logger, services) {
661
666
  title: "Init workspace",
662
667
  description: DESCRIPTION14,
663
668
  inputSchema: {
664
- root: z12.string().optional().describe("Workspace root to scan. Defaults to the directory chamba runs in.")
669
+ root: z12.string().optional().describe("Workspace root to scan. Defaults to the directory chamba runs in."),
670
+ createVault: z12.boolean().optional().describe("Bootstrap an Obsidian vault at the root when none is found (default true).")
665
671
  }
666
672
  },
667
- async ({ root }) => {
673
+ async ({ root, createVault }) => {
668
674
  const workspaceRoot = root ?? services.cwd;
669
675
  const wsPath = joinPath4(workspaceRoot, WORKSPACE_RELATIVE_PATH);
670
- if (await services.fs.exists(wsPath)) {
671
- const currentContents = await services.fs.readFile(wsPath);
672
- logger.info({ tool: TOOL_NAME14, wsPath }, "workspace.md already exists, not overwriting");
673
- return {
674
- content: [
675
- {
676
- type: "text",
677
- text: `\`${WORKSPACE_RELATIVE_PATH}\` already exists at ${wsPath}; not overwriting.
678
-
679
- Current contents:
680
-
681
- ${currentContents}`
682
- }
683
- ]
684
- };
676
+ const workspace = await new WorkspaceScanner4(services.fs).scan(workspaceRoot);
677
+ const wsExisted = await services.fs.exists(wsPath);
678
+ let markdown;
679
+ if (wsExisted) {
680
+ markdown = await services.fs.readFile(wsPath);
681
+ } else {
682
+ markdown = renderWorkspaceMarkdown(workspace);
683
+ await services.fs.mkdir(joinPath4(workspaceRoot, WORKSPACE_DIR4));
684
+ await services.fs.writeFile(wsPath, markdown);
685
+ }
686
+ const wsLine = wsExisted ? `\`${WORKSPACE_RELATIVE_PATH}\` already exists at ${wsPath}; not overwriting.` : `Created \`${WORKSPACE_RELATIVE_PATH}\` at ${wsPath}.`;
687
+ let vaultLine = "Vault: skipped (createVault: false).";
688
+ if (createVault !== false) {
689
+ const detection = await new ObsidianDetector4(services.fs).detect({
690
+ explicitPath: services.obsidianVaultPath,
691
+ searchRoots: obsidianSearchRoots(services)
692
+ });
693
+ if (detection.found) {
694
+ vaultLine = `Vault: using the existing one at ${detection.path}; left it untouched.`;
695
+ } else {
696
+ const seeded = await new VaultInitializer(services.fs, services.clock).seed({
697
+ vaultPath: workspaceRoot,
698
+ workspace
699
+ });
700
+ vaultLine = `Vault: none found \u2014 created one at the workspace root and seeded \`${VAULT_OVERVIEW_FILE}\`. Add \`.obsidian/\` to .gitignore if you don't want it committed.`;
701
+ logger.info({ tool: TOOL_NAME14, vault: seeded.vaultPath }, "vault bootstrapped");
702
+ }
685
703
  }
686
- const scanner = new WorkspaceScanner4(services.fs);
687
- const workspace = await scanner.scan(workspaceRoot);
688
- const markdown = renderWorkspaceMarkdown(workspace);
689
- await services.fs.mkdir(joinPath4(workspaceRoot, WORKSPACE_DIR4));
690
- await services.fs.writeFile(wsPath, markdown);
691
704
  logger.info(
692
- { tool: TOOL_NAME14, wsPath, projects: workspace.projects.length },
693
- "workspace.md created"
705
+ { tool: TOOL_NAME14, wsPath, wsExisted, projects: workspace.projects.length },
706
+ "workspace init"
694
707
  );
695
- return {
696
- content: [
697
- {
698
- type: "text",
699
- text: `Created \`${WORKSPACE_RELATIVE_PATH}\` at ${wsPath}.
708
+ return { content: [{ type: "text", text: `${wsLine}
709
+ ${vaultLine}
700
710
 
701
- ${markdown}`
702
- }
703
- ]
704
- };
711
+ ${markdown}` }] };
705
712
  }
706
713
  );
707
714
  }
@@ -827,7 +834,22 @@ function createServer(logger, services = createNodeServices()) {
827
834
  }
828
835
 
829
836
  // src/main.ts
837
+ function readPackageVersion() {
838
+ try {
839
+ const pkgPath = fileURLToPath(new URL("../package.json", import.meta.url));
840
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
841
+ return pkg.version ?? "unknown";
842
+ } catch {
843
+ return "unknown";
844
+ }
845
+ }
830
846
  async function main() {
847
+ const flag = process.argv[2];
848
+ if (flag === "--version" || flag === "-v") {
849
+ process.stdout.write(`${readPackageVersion()}
850
+ `);
851
+ return;
852
+ }
831
853
  const logger = createLogger();
832
854
  const server = createServer(logger);
833
855
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chamba/mcp",
3
- "version": "0.5.2",
3
+ "version": "0.6.1",
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.5.2",
40
- "@chamba/core": "0.5.2"
39
+ "@chamba/core": "0.6.1",
40
+ "@chamba/adapters": "0.6.1"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.0.0",