obsidian-mcp-server 1.5.1 → 1.5.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.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.8.3-blue.svg)](https://www.typescriptlang.org/)
4
4
  [![Model Context Protocol](https://img.shields.io/badge/MCP-1.8.0-green.svg)](https://modelcontextprotocol.io/)
5
- [![Version](https://img.shields.io/badge/Version-1.5.1-blue.svg)]()
5
+ [![Version](https://img.shields.io/badge/Version-1.5.2-blue.svg)]()
6
6
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
7
  [![Status](https://img.shields.io/badge/Status-Stable-green.svg)]()
8
8
  [![GitHub](https://img.shields.io/github/stars/cyanheads/obsidian-mcp-server?style=social)](https://github.com/cyanheads/obsidian-mcp-server)
@@ -1,3 +1,4 @@
1
+ import pLimit from 'p-limit'; // Import p-limit
1
2
  import { PropertyManager } from "../tools/properties/manager.js";
2
3
  import { sep } from "path";
3
4
  import { createLogger, ErrorCategoryType } from "../utils/logging.js";
@@ -65,12 +66,15 @@ export class TagResource {
65
66
  };
66
67
  const results = await this.client.searchJson(query);
67
68
  this.tagCache.clear();
68
- // Create promises for processing each file in parallel
69
+ // Create a limiter with a concurrency of 3 (reduced from 10)
70
+ const limit = pLimit(3);
71
+ // Create promises for processing each file with concurrency limiting
69
72
  const processingPromises = results
70
73
  .filter(result => 'filename' in result) // Ensure filename exists
71
- .map(async (result) => {
74
+ .map((result) => limit(async () => {
72
75
  const filename = result.filename;
73
76
  try {
77
+ // This call is now rate-limited
74
78
  const content = await this.client.getFileContents(filename);
75
79
  // Only extract tags from frontmatter YAML
76
80
  const properties = this.propertyManager.parseProperties(content);
@@ -80,7 +84,7 @@ export class TagResource {
80
84
  logger.error(`Failed to process file ${filename}:`, errorToObject(error));
81
85
  return { filename, error: true }; // Mark as failed
82
86
  }
83
- });
87
+ })); // Close the limiter wrapper
84
88
  // Execute promises in parallel and wait for all to settle
85
89
  const processedResults = await Promise.allSettled(processingPromises);
86
90
  // Populate the cache from settled results
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "obsidian-mcp-server",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "description": "Model Context Protocol (MCP) server designed for LLMs to interact with Obsidian vaults. Provides secure, token-aware tools for seamless knowledge base management through a standardized interface.",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -29,6 +29,7 @@
29
29
  "eslint-config-prettier": "^10.1.1",
30
30
  "eslint-plugin-prettier": "^5.2.6",
31
31
  "nanoid": "^5.1.5",
32
+ "p-limit": "^6.2.0",
32
33
  "prettier": "^3.5.3",
33
34
  "tiktoken": "^1.0.20",
34
35
  "typescript": "^5.8.3",
@@ -4,6 +4,7 @@
4
4
  import { Resource, TextContent } from "@modelcontextprotocol/sdk/types.js";
5
5
  import { ObsidianClient } from "../obsidian/client.js";
6
6
  import { JsonLogicQuery } from "../obsidian/types.js";
7
+ import pLimit from 'p-limit'; // Import p-limit
7
8
  import { PropertyManager } from "../tools/properties/manager.js";
8
9
  import { join, sep } from "path";
9
10
  import { createLogger, ErrorCategoryType } from "../utils/logging.js";
@@ -78,13 +79,17 @@ export class TagResource {
78
79
  const results = await this.client.searchJson(query);
79
80
  this.tagCache.clear();
80
81
 
81
- // Create promises for processing each file in parallel
82
+ // Create a limiter with a concurrency of 3 (reduced from 10)
83
+ const limit = pLimit(3);
84
+
85
+ // Create promises for processing each file with concurrency limiting
82
86
  const processingPromises = results
83
87
  .filter(result => 'filename' in result) // Ensure filename exists
84
- .map(async (result) => {
88
+ .map((result) => limit(async () => { // Wrap the async function with the limiter
85
89
  const filename = result.filename;
86
90
  try {
87
- const content = await this.client.getFileContents(filename);
91
+ // This call is now rate-limited
92
+ const content = await this.client.getFileContents(filename);
88
93
  // Only extract tags from frontmatter YAML
89
94
  const properties = this.propertyManager.parseProperties(content);
90
95
  return { filename, tags: properties.tags || [] };
@@ -92,7 +97,7 @@ export class TagResource {
92
97
  logger.error(`Failed to process file ${filename}:`, errorToObject(error));
93
98
  return { filename, error: true }; // Mark as failed
94
99
  }
95
- });
100
+ })); // Close the limiter wrapper
96
101
 
97
102
  // Execute promises in parallel and wait for all to settle
98
103
  const processedResults = await Promise.allSettled(processingPromises);