@sunub/obsidian-mcp-server 0.0.2 → 0.0.4

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.
@@ -0,0 +1,55 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { Command } from "commander";
4
+ import dotenv from "dotenv";
5
+ import { z } from "zod/v4";
6
+ dotenv.config({ debug: false, quiet: true });
7
+ const vaultPathSchema = z
8
+ .string()
9
+ .min(1, "Vault path는 비어 있을 수 없습니다.")
10
+ .trim()
11
+ .transform((val) => resolve(val)) // 입력받은 경로를 절대 경로로 변환
12
+ .refine((val) => existsSync(val), {
13
+ message: "파일 시스템에 해당 경로가 존재하지 않습니다.",
14
+ })
15
+ .refine((val) => {
16
+ try {
17
+ return statSync(val).isDirectory();
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }, {
23
+ message: "지정된 경로가 디렉토리가 아닙니다.",
24
+ });
25
+ export const configSchema = z.object({
26
+ vaultPath: vaultPathSchema,
27
+ loggingLevel: z.enum(["debug", "info", "warn", "error"]).default("info"),
28
+ });
29
+ const state = {
30
+ vaultPath: process.env.VAULT_DIR_PATH || "",
31
+ loggingLevel: "info",
32
+ };
33
+ export function getOptions() {
34
+ const program = new Command()
35
+ .name("obsidian-mcp-server")
36
+ .description("MCP Server for Obsidian Vault")
37
+ .option("--vault-path <path>", "Path to the Obsidian vault directory", process.env.VAULT_DIR_PATH ?? "")
38
+ .option("--logging-level <level>", "Logging level (debug, info, warn, error)", process.env.LOGGING_LEVEL ?? "info")
39
+ .allowUnknownOption()
40
+ .parse(process.argv);
41
+ const options = program.opts();
42
+ const parseResult = configSchema.safeParse(options);
43
+ if (!parseResult.success) {
44
+ console.error("Configuration Error:");
45
+ parseResult.error.issues.forEach((issue) => {
46
+ console.error(` - ${issue.path.join(".")}: ${issue.message}`);
47
+ });
48
+ console.info("\n사용 방법: Environment variables 에 VAULT_DIR_PATH 설정 또는 명령줄 인수 --vault-path <path>를 통해 올바른 구성을 제공하세요.");
49
+ return false;
50
+ }
51
+ state.vaultPath = parseResult.data.vaultPath;
52
+ state.loggingLevel = parseResult.data.loggingLevel;
53
+ return state;
54
+ }
55
+ export default state;
package/build/index.js CHANGED
@@ -1,10 +1,17 @@
1
+ #!/usr/bin/env node
1
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { getOptions } from "./config.js";
2
4
  import createMcpServer from "./server.js";
3
5
  export default function smitheryEntryPoint() {
4
6
  const server = createMcpServer();
5
7
  return server.server;
6
8
  }
7
9
  async function main() {
10
+ const options = getOptions();
11
+ if (!options) {
12
+ console.error("올바르지 않은 설정으로 인해 서버를 시작할 수 없습니다.");
13
+ process.exit(1);
14
+ }
8
15
  try {
9
16
  const server = createMcpServer();
10
17
  const transport = new StdioServerTransport();
@@ -1,5 +1,5 @@
1
+ import state from "../../config.js";
1
2
  import { getGlobalVaultManager } from "../../utils/getVaultManager.js";
2
- import { getParsedVaultPath } from "../../utils/parseVaultPath.js";
3
3
  import { execute as writePropertyExecute } from "../write_property/index.js";
4
4
  import { createDocumentWithPropertiesParamsSchema, } from "./params.js";
5
5
  export const name = "create_document_with_properties";
@@ -23,7 +23,7 @@ export const register = (mcpServer) => {
23
23
  }, execute);
24
24
  };
25
25
  export const execute = async (params) => {
26
- const vaultDirPath = getParsedVaultPath();
26
+ const vaultDirPath = state.vaultPath;
27
27
  if (!vaultDirPath) {
28
28
  return {
29
29
  isError: true,
@@ -1,5 +1,5 @@
1
+ import state from "../../config.js";
1
2
  import { getGlobalVaultManager } from "../../utils/getVaultManager.js";
2
- import { getParsedVaultPath } from "../../utils/parseVaultPath.js";
3
3
  import { organizeAttachmentsParamsSchema, } from "./params.js";
4
4
  import { genreateOrganizationTasks } from "./utils.js";
5
5
  export const name = "organize_attachments";
@@ -33,7 +33,7 @@ export const register = (mcpServer) => {
33
33
  }, execute);
34
34
  };
35
35
  export const execute = async (params) => {
36
- const vaultDirPath = getParsedVaultPath();
36
+ const vaultDirPath = state.vaultPath;
37
37
  if (!vaultDirPath) {
38
38
  return {
39
39
  isError: true,
@@ -1,5 +1,5 @@
1
+ import state from "../../config.js";
1
2
  import { getGlobalVaultManager } from "../../utils/getVaultManager.js";
2
- import { getParsedVaultPath } from "../../utils/parseVaultPath.js";
3
3
  import { obsidianContentQueryParamsZod, } from "./params.js";
4
4
  import { listAllDocuments, readSpecificFile, searchDocuments, statsAllDocuments, } from "./utils.js";
5
5
  export const name = "vault";
@@ -30,7 +30,7 @@ export const register = (mcpServer) => {
30
30
  }, execute);
31
31
  };
32
32
  export const execute = async (params) => {
33
- const vaultDirPath = getParsedVaultPath();
33
+ const vaultDirPath = state.vaultPath;
34
34
  // Vault 경로 검증
35
35
  if (!vaultDirPath) {
36
36
  return {
@@ -1,5 +1,5 @@
1
+ import state from "../../config.js";
1
2
  import { getGlobalVaultManager } from "../../utils/getVaultManager.js";
2
- import { getParsedVaultPath } from "../../utils/parseVaultPath.js";
3
3
  import { obsidianPropertyParamsSchema, } from "./params.js";
4
4
  export const name = "write_property";
5
5
  export const annotations = {
@@ -61,7 +61,7 @@ export const register = (mcpServer) => {
61
61
  };
62
62
  export const execute = async (params) => {
63
63
  const response = { content: [], isError: false };
64
- const vaultDirPath = getParsedVaultPath();
64
+ const vaultDirPath = state.vaultPath;
65
65
  if (!vaultDirPath) {
66
66
  response.content.push({
67
67
  type: "text",
@@ -1,11 +1,11 @@
1
- import { getParsedVaultPath } from "./parseVaultPath.js";
1
+ import state from "../config.js";
2
2
  import { VaultManager } from "./VaultManager.js";
3
3
  let instance = null;
4
4
  export function getGlobalVaultManager() {
5
5
  if (instance) {
6
6
  return instance;
7
7
  }
8
- const vaultPath = getParsedVaultPath();
8
+ const vaultPath = state.vaultPath;
9
9
  if (!vaultPath) {
10
10
  throw new Error("VAULT_DIR_PATH environment variable is not set");
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunub/obsidian-mcp-server",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "A server for the Obsidian Model Context Protocol.",
5
5
  "keywords": [
6
6
  "obsidian",
@@ -39,6 +39,7 @@
39
39
  "license": "ISC",
40
40
  "dependencies": {
41
41
  "@modelcontextprotocol/sdk": "^1.17.5",
42
+ "commander": "^14.0.2",
42
43
  "dotenv": "^17.2.2",
43
44
  "gray-matter": "^4.0.3",
44
45
  "zod": "^3.25.76"
@@ -1,18 +0,0 @@
1
- import os from "node:os";
2
- import dotenv from "dotenv";
3
- dotenv.config({ debug: false });
4
- export const VAULT_DIR_PATH = process.env.VAULT_DIR_PATH || "";
5
- function isWindowsPath(path) {
6
- return os.platform() === "win32" && /^[a-zA-Z]:\\/.test(path);
7
- }
8
- function parseWindosPathToLinux(path) {
9
- if (!isWindowsPath(path)) {
10
- throw new Error("Not a valid Windows path");
11
- }
12
- const driveLetter = path[0].toLowerCase();
13
- const pathWithoutDrive = path.slice(2).replace(/\\/g, "/");
14
- return `/mnt/${driveLetter}/${pathWithoutDrive}`;
15
- }
16
- export const getParsedVaultPath = () => isWindowsPath(VAULT_DIR_PATH)
17
- ? parseWindosPathToLinux(VAULT_DIR_PATH)
18
- : VAULT_DIR_PATH;