obsidian-mcp-server 1.2.6 → 1.4.0
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 +54 -10
- package/build/index.js +12 -3
- package/build/mcp/handlers.js +138 -0
- package/build/mcp/index.js +7 -0
- package/build/mcp/server.js +131 -0
- package/build/mcp/types.js +7 -0
- package/build/{obsidian.js → obsidian/client.js} +156 -104
- package/build/obsidian/errors.js +75 -0
- package/build/obsidian/index.js +7 -0
- package/build/obsidian/types.js +12 -0
- package/build/resources/index.js +15 -0
- package/build/{resources.js → resources/tags.js} +35 -14
- package/build/resources/types.js +5 -0
- package/build/tools/base.js +78 -0
- package/build/tools/files/content.js +171 -0
- package/build/tools/files/index.js +22 -0
- package/build/tools/files/list.js +133 -0
- package/build/tools/index.js +31 -0
- package/build/tools/properties/index.js +19 -0
- package/build/{properties.js → tools/properties/manager.js} +50 -13
- package/build/{propertyTools.js → tools/properties/tools.js} +22 -6
- package/build/{propertyTypes.js → tools/properties/types.js} +19 -7
- package/build/tools/search/complex.js +203 -0
- package/build/tools/search/index.js +20 -0
- package/build/tools/search/simple.js +127 -0
- package/build/utils/errors.js +59 -0
- package/build/utils/index.js +9 -0
- package/build/utils/logging.js +119 -0
- package/build/utils/rate-limiting.js +94 -0
- package/build/utils/tokenization.js +62 -0
- package/build/utils/validation.js +88 -0
- package/examples/README.md +48 -0
- package/examples/append-content.md +63 -0
- package/examples/complex-search.md +117 -0
- package/examples/find-in-file.md +94 -0
- package/examples/get-file-contents.md +72 -0
- package/examples/get-properties.md +89 -0
- package/examples/list-files-in-dir.md +55 -0
- package/examples/list-files-in-vault.md +53 -0
- package/examples/patch-content.md +60 -0
- package/examples/update-properties.md +126 -0
- package/mcp-client-config.example.json +23 -0
- package/package.json +4 -3
- package/src/index.ts +13 -3
- package/src/mcp/handlers.ts +183 -0
- package/src/mcp/index.ts +6 -0
- package/src/mcp/server.ts +162 -0
- package/src/mcp/types.ts +46 -0
- package/src/{obsidian.ts → obsidian/client.ts} +174 -134
- package/src/obsidian/errors.ts +105 -0
- package/src/obsidian/index.ts +6 -0
- package/src/obsidian/types.ts +124 -0
- package/src/resources/index.ts +17 -0
- package/src/{resources.ts → resources/tags.ts} +42 -16
- package/src/resources/types.ts +30 -0
- package/src/tools/base.ts +112 -0
- package/src/tools/files/content.ts +206 -0
- package/src/tools/files/index.ts +31 -0
- package/src/tools/files/list.ts +150 -0
- package/src/tools/index.ts +38 -0
- package/src/tools/properties/index.ts +21 -0
- package/src/{properties.ts → tools/properties/manager.ts} +54 -13
- package/src/{propertyTools.ts → tools/properties/tools.ts} +33 -7
- package/src/{propertyTypes.ts → tools/properties/types.ts} +31 -7
- package/src/tools/search/complex.ts +231 -0
- package/src/tools/search/index.ts +22 -0
- package/src/tools/search/simple.ts +147 -0
- package/src/utils/errors.ts +69 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/logging.ts +146 -0
- package/src/utils/rate-limiting.ts +114 -0
- package/src/utils/tokenization.ts +71 -0
- package/src/utils/validation.ts +95 -0
- package/build/server.js +0 -238
- package/build/tools.js +0 -863
- package/build/types.js +0 -37
- package/src/server.ts +0 -308
- package/src/tools.ts +0 -946
- package/src/types.ts +0 -184
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { PropertyManager } from "
|
|
1
|
+
import { PropertyManager } from "../tools/properties/manager.js";
|
|
2
|
+
import { sep } from "path";
|
|
3
|
+
import { createLogger } from "../utils/logging.js";
|
|
4
|
+
// Create a logger for tag resources
|
|
5
|
+
const logger = createLogger('TagResource');
|
|
6
|
+
/**
|
|
7
|
+
* Resource for providing tags used in the Obsidian vault
|
|
8
|
+
*/
|
|
2
9
|
export class TagResource {
|
|
3
10
|
client;
|
|
4
|
-
static TAG_PATTERN = /#[a-zA-Z0-9_-]+/g;
|
|
5
11
|
tagCache = new Map();
|
|
6
12
|
propertyManager;
|
|
7
13
|
isInitialized = false;
|
|
@@ -12,6 +18,9 @@ export class TagResource {
|
|
|
12
18
|
this.propertyManager = new PropertyManager(client);
|
|
13
19
|
this.initializeCache();
|
|
14
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Get resource description for the MCP server
|
|
23
|
+
*/
|
|
15
24
|
getResourceDescription() {
|
|
16
25
|
return {
|
|
17
26
|
uri: "obsidian://tags",
|
|
@@ -20,11 +29,15 @@ export class TagResource {
|
|
|
20
29
|
mimeType: "application/json"
|
|
21
30
|
};
|
|
22
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Initialize the tag cache
|
|
34
|
+
*/
|
|
23
35
|
async initializeCache() {
|
|
24
36
|
try {
|
|
25
|
-
|
|
37
|
+
logger.info('Initializing tag cache');
|
|
38
|
+
// Get all markdown files using platform-agnostic path pattern
|
|
26
39
|
const query = {
|
|
27
|
-
"glob": [
|
|
40
|
+
"glob": [`**${sep}*.md`.replace(/\\/g, '/'), { "var": "path" }]
|
|
28
41
|
};
|
|
29
42
|
const results = await this.client.searchJson(query);
|
|
30
43
|
this.tagCache.clear();
|
|
@@ -34,46 +47,53 @@ export class TagResource {
|
|
|
34
47
|
continue;
|
|
35
48
|
try {
|
|
36
49
|
const content = await this.client.getFileContents(result.filename);
|
|
37
|
-
//
|
|
50
|
+
// Only extract tags from frontmatter YAML
|
|
38
51
|
const properties = this.propertyManager.parseProperties(content);
|
|
39
52
|
if (properties.tags) {
|
|
40
53
|
properties.tags.forEach((tag) => {
|
|
41
54
|
this.addTag(tag, result.filename);
|
|
42
55
|
});
|
|
43
56
|
}
|
|
44
|
-
// Extract inline tags
|
|
45
|
-
const inlineTags = content.match(TagResource.TAG_PATTERN) || [];
|
|
46
|
-
inlineTags.forEach(tag => {
|
|
47
|
-
this.addTag(tag, result.filename);
|
|
48
|
-
});
|
|
49
57
|
}
|
|
50
58
|
catch (error) {
|
|
51
|
-
|
|
59
|
+
logger.error(`Failed to process file ${result.filename}:`, error);
|
|
52
60
|
}
|
|
53
61
|
}
|
|
54
62
|
this.isInitialized = true;
|
|
55
63
|
this.lastUpdate = Date.now();
|
|
64
|
+
logger.info(`Tag cache initialized with ${this.tagCache.size} unique tags`);
|
|
56
65
|
}
|
|
57
66
|
catch (error) {
|
|
58
|
-
|
|
67
|
+
logger.error("Failed to initialize tag cache:", error);
|
|
59
68
|
throw error;
|
|
60
69
|
}
|
|
61
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Add a tag to the cache
|
|
73
|
+
*/
|
|
62
74
|
addTag(tag, filepath) {
|
|
63
75
|
if (!this.tagCache.has(tag)) {
|
|
64
76
|
this.tagCache.set(tag, new Set());
|
|
65
77
|
}
|
|
66
78
|
this.tagCache.get(tag).add(filepath);
|
|
67
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Update the cache if needed
|
|
82
|
+
*/
|
|
68
83
|
async updateCacheIfNeeded() {
|
|
69
84
|
const now = Date.now();
|
|
70
85
|
if (now - this.lastUpdate > this.updateInterval) {
|
|
86
|
+
logger.debug('Tag cache needs update, refreshing...');
|
|
71
87
|
await this.initializeCache();
|
|
72
88
|
}
|
|
73
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the content for the resource
|
|
92
|
+
*/
|
|
74
93
|
async getContent() {
|
|
75
94
|
try {
|
|
76
95
|
if (!this.isInitialized) {
|
|
96
|
+
logger.info('Tag cache not initialized, initializing now');
|
|
77
97
|
await this.initializeCache();
|
|
78
98
|
}
|
|
79
99
|
else {
|
|
@@ -96,6 +116,7 @@ export class TagResource {
|
|
|
96
116
|
lastUpdate: this.lastUpdate
|
|
97
117
|
}
|
|
98
118
|
};
|
|
119
|
+
logger.debug(`Returning tag resource with ${response.tags.length} tags`);
|
|
99
120
|
return [{
|
|
100
121
|
type: "text",
|
|
101
122
|
text: JSON.stringify(response, null, 2),
|
|
@@ -103,9 +124,9 @@ export class TagResource {
|
|
|
103
124
|
}];
|
|
104
125
|
}
|
|
105
126
|
catch (error) {
|
|
106
|
-
|
|
127
|
+
logger.error("Failed to get tags:", error);
|
|
107
128
|
throw error;
|
|
108
129
|
}
|
|
109
130
|
}
|
|
110
131
|
}
|
|
111
|
-
//# sourceMappingURL=
|
|
132
|
+
//# sourceMappingURL=tags.js.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ObsidianError } from "../utils/errors.js";
|
|
2
|
+
import { tokenCounter } from "../utils/tokenization.js";
|
|
3
|
+
import { createLogger } from "../utils/logging.js";
|
|
4
|
+
// Create a logger for tool operations
|
|
5
|
+
const logger = createLogger('Tools');
|
|
6
|
+
/**
|
|
7
|
+
* Base class for all tool handlers with common functionality
|
|
8
|
+
*/
|
|
9
|
+
export class BaseToolHandler {
|
|
10
|
+
name;
|
|
11
|
+
client;
|
|
12
|
+
/**
|
|
13
|
+
* Create a new tool handler
|
|
14
|
+
* @param name The name of the tool
|
|
15
|
+
* @param client The ObsidianClient instance
|
|
16
|
+
*/
|
|
17
|
+
constructor(name, client) {
|
|
18
|
+
this.name = name;
|
|
19
|
+
this.client = client;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create a standardized response from any content type
|
|
23
|
+
* @param content The content to format for response
|
|
24
|
+
* @returns An array of TextContent objects
|
|
25
|
+
*/
|
|
26
|
+
createResponse(content) {
|
|
27
|
+
let text;
|
|
28
|
+
// Handle different content types
|
|
29
|
+
if (typeof content === 'string') {
|
|
30
|
+
text = content;
|
|
31
|
+
}
|
|
32
|
+
else if (content instanceof Buffer) {
|
|
33
|
+
text = content.toString('utf-8');
|
|
34
|
+
}
|
|
35
|
+
else if (Array.isArray(content) && content.every(item => typeof item === 'string')) {
|
|
36
|
+
text = content.join('\n');
|
|
37
|
+
}
|
|
38
|
+
else if (content instanceof Error) {
|
|
39
|
+
text = `Error: ${content.message}\n${content.stack || ''}`;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
try {
|
|
43
|
+
text = JSON.stringify(content, null, 2);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
text = String(content);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Count tokens and truncate if necessary
|
|
50
|
+
const originalTokenCount = tokenCounter.countTokens(text);
|
|
51
|
+
const truncatedText = tokenCounter.truncateToTokenLimit(text);
|
|
52
|
+
const finalTokenCount = tokenCounter.countTokens(truncatedText);
|
|
53
|
+
if (originalTokenCount > finalTokenCount) {
|
|
54
|
+
logger.debug(`[${this.name}] Response truncated:`, `original tokens=${originalTokenCount}`, `truncated tokens=${finalTokenCount}`);
|
|
55
|
+
}
|
|
56
|
+
return [{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: truncatedText
|
|
59
|
+
}];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Standard error handling for tool execution
|
|
63
|
+
* @param error The error to handle
|
|
64
|
+
* @throws ObsidianError
|
|
65
|
+
*/
|
|
66
|
+
handleError(error) {
|
|
67
|
+
if (error instanceof ObsidianError) {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
if (error instanceof Error) {
|
|
71
|
+
throw new ObsidianError(`Tool '${this.name}' execution failed: ${error.message}`, 50000, // Internal server error
|
|
72
|
+
{ originalError: error.stack });
|
|
73
|
+
}
|
|
74
|
+
throw new ObsidianError(`Tool '${this.name}' execution failed with unknown error`, 50000, // Internal server error
|
|
75
|
+
{ error });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { BaseToolHandler } from "../base.js";
|
|
2
|
+
import { createLogger } from "../../utils/logging.js";
|
|
3
|
+
// Create a logger for file content operations
|
|
4
|
+
const logger = createLogger('FileContentTools');
|
|
5
|
+
/**
|
|
6
|
+
* Tool names for file content operations
|
|
7
|
+
*/
|
|
8
|
+
export const FILE_CONTENT_TOOL_NAMES = {
|
|
9
|
+
GET_FILE_CONTENTS: "obsidian_get_file_contents",
|
|
10
|
+
APPEND_CONTENT: "obsidian_append_content",
|
|
11
|
+
PATCH_CONTENT: "obsidian_patch_content"
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Tool handler for getting file contents
|
|
15
|
+
*/
|
|
16
|
+
export class GetFileContentsToolHandler extends BaseToolHandler {
|
|
17
|
+
constructor(client) {
|
|
18
|
+
super(FILE_CONTENT_TOOL_NAMES.GET_FILE_CONTENTS, client);
|
|
19
|
+
}
|
|
20
|
+
getToolDescription() {
|
|
21
|
+
return {
|
|
22
|
+
name: this.name,
|
|
23
|
+
description: "Return the content of a single file in your vault. Supports markdown files, text files, and other readable formats. Returns the raw content including any YAML frontmatter.",
|
|
24
|
+
examples: [
|
|
25
|
+
{
|
|
26
|
+
description: "Get content of a markdown note",
|
|
27
|
+
args: {
|
|
28
|
+
filepath: "Projects/research.md"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
description: "Get content of a configuration file",
|
|
33
|
+
args: {
|
|
34
|
+
filepath: "configs/settings.yml"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
filepath: {
|
|
42
|
+
type: "string",
|
|
43
|
+
description: "Path to the relevant file (relative to your vault root).",
|
|
44
|
+
format: "path"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
required: ["filepath"]
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async runTool(args) {
|
|
52
|
+
try {
|
|
53
|
+
logger.debug(`Getting contents of file: ${args.filepath}`);
|
|
54
|
+
const content = await this.client.getFileContents(args.filepath);
|
|
55
|
+
return this.createResponse(content);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return this.handleError(error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Tool handler for appending content to a file
|
|
64
|
+
*/
|
|
65
|
+
export class AppendContentToolHandler extends BaseToolHandler {
|
|
66
|
+
constructor(client) {
|
|
67
|
+
super(FILE_CONTENT_TOOL_NAMES.APPEND_CONTENT, client);
|
|
68
|
+
}
|
|
69
|
+
getToolDescription() {
|
|
70
|
+
return {
|
|
71
|
+
name: this.name,
|
|
72
|
+
description: "Append content to a new or existing file in the vault.",
|
|
73
|
+
examples: [
|
|
74
|
+
{
|
|
75
|
+
description: "Append a new task",
|
|
76
|
+
args: {
|
|
77
|
+
filepath: "tasks.md",
|
|
78
|
+
content: "- [ ] New task to complete"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
description: "Append meeting notes",
|
|
83
|
+
args: {
|
|
84
|
+
filepath: "meetings/2025-01-23.md",
|
|
85
|
+
content: "## Meeting Notes\n\n- Discussed project timeline\n- Assigned tasks"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
inputSchema: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
filepath: {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: "Path to the file (relative to vault root)",
|
|
95
|
+
format: "path"
|
|
96
|
+
},
|
|
97
|
+
content: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "Content to append to the file"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
required: ["filepath", "content"]
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async runTool(args) {
|
|
107
|
+
try {
|
|
108
|
+
logger.debug(`Appending content to file: ${args.filepath}`);
|
|
109
|
+
await this.client.appendContent(args.filepath, args.content);
|
|
110
|
+
return this.createResponse({
|
|
111
|
+
message: `Successfully appended content to ${args.filepath}`,
|
|
112
|
+
success: true
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
return this.handleError(error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Tool handler for updating file content
|
|
122
|
+
*/
|
|
123
|
+
export class PatchContentToolHandler extends BaseToolHandler {
|
|
124
|
+
constructor(client) {
|
|
125
|
+
super(FILE_CONTENT_TOOL_NAMES.PATCH_CONTENT, client);
|
|
126
|
+
}
|
|
127
|
+
getToolDescription() {
|
|
128
|
+
return {
|
|
129
|
+
name: this.name,
|
|
130
|
+
description: "Update the entire content of an existing note or create a new one.",
|
|
131
|
+
examples: [
|
|
132
|
+
{
|
|
133
|
+
description: "Update a note's content",
|
|
134
|
+
args: {
|
|
135
|
+
filepath: "project.md",
|
|
136
|
+
content: "# Project Notes\n\nThis will replace the entire content of the note."
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
inputSchema: {
|
|
141
|
+
type: "object",
|
|
142
|
+
properties: {
|
|
143
|
+
filepath: {
|
|
144
|
+
type: "string",
|
|
145
|
+
description: "Path to the file (relative to vault root)",
|
|
146
|
+
format: "path"
|
|
147
|
+
},
|
|
148
|
+
content: {
|
|
149
|
+
type: "string",
|
|
150
|
+
description: "New content for the note (replaces existing content)"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
required: ["filepath", "content"]
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
async runTool(args) {
|
|
158
|
+
try {
|
|
159
|
+
logger.debug(`Updating content of file: ${args.filepath}`);
|
|
160
|
+
await this.client.updateContent(args.filepath, args.content);
|
|
161
|
+
return this.createResponse({
|
|
162
|
+
message: `Successfully updated content in ${args.filepath}`,
|
|
163
|
+
success: true
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return this.handleError(error);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File operation tools exports
|
|
3
|
+
*/
|
|
4
|
+
export * from './list.js';
|
|
5
|
+
export * from './content.js';
|
|
6
|
+
import { ListFilesInVaultToolHandler, ListFilesInDirToolHandler } from './list.js';
|
|
7
|
+
import { GetFileContentsToolHandler, AppendContentToolHandler, PatchContentToolHandler } from './content.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create all file-related tool handlers
|
|
10
|
+
* @param client The ObsidianClient instance
|
|
11
|
+
* @returns Array of file tool handlers
|
|
12
|
+
*/
|
|
13
|
+
export function createFileToolHandlers(client) {
|
|
14
|
+
return [
|
|
15
|
+
new ListFilesInVaultToolHandler(client),
|
|
16
|
+
new ListFilesInDirToolHandler(client),
|
|
17
|
+
new GetFileContentsToolHandler(client),
|
|
18
|
+
new AppendContentToolHandler(client),
|
|
19
|
+
new PatchContentToolHandler(client)
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { BaseToolHandler } from "../base.js";
|
|
2
|
+
import { createLogger } from "../../utils/logging.js";
|
|
3
|
+
// Create a logger for file operations
|
|
4
|
+
const logger = createLogger('FileTools');
|
|
5
|
+
/**
|
|
6
|
+
* Tool names for file listing operations
|
|
7
|
+
*/
|
|
8
|
+
export const FILE_TOOL_NAMES = {
|
|
9
|
+
LIST_FILES_IN_VAULT: "obsidian_list_files_in_vault",
|
|
10
|
+
LIST_FILES_IN_DIR: "obsidian_list_files_in_dir"
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Tool handler for listing all files in the vault
|
|
14
|
+
*/
|
|
15
|
+
export class ListFilesInVaultToolHandler extends BaseToolHandler {
|
|
16
|
+
constructor(client) {
|
|
17
|
+
super(FILE_TOOL_NAMES.LIST_FILES_IN_VAULT, client);
|
|
18
|
+
}
|
|
19
|
+
getToolDescription() {
|
|
20
|
+
return {
|
|
21
|
+
name: this.name,
|
|
22
|
+
description: "Lists all files and directories in the root directory of your Obsidian vault. Returns a hierarchical structure of files and folders, including metadata like file type.",
|
|
23
|
+
examples: [
|
|
24
|
+
{
|
|
25
|
+
description: "List all files in vault",
|
|
26
|
+
args: {}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
description: "Example response",
|
|
30
|
+
args: {},
|
|
31
|
+
response: [
|
|
32
|
+
{
|
|
33
|
+
"path": "Daily Notes",
|
|
34
|
+
"type": "folder",
|
|
35
|
+
"children": [
|
|
36
|
+
{ "path": "Daily Notes/2025-01-24.md", "type": "file" }
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"path": "Projects",
|
|
41
|
+
"type": "folder",
|
|
42
|
+
"children": [
|
|
43
|
+
{ "path": "Projects/MCP.md", "type": "file" }
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: {},
|
|
52
|
+
required: []
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async runTool() {
|
|
57
|
+
try {
|
|
58
|
+
logger.debug('Listing all files in vault');
|
|
59
|
+
const files = await this.client.listFilesInVault();
|
|
60
|
+
return this.createResponse(files);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return this.handleError(error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Tool handler for listing files in a specific directory
|
|
69
|
+
*/
|
|
70
|
+
export class ListFilesInDirToolHandler extends BaseToolHandler {
|
|
71
|
+
constructor(client) {
|
|
72
|
+
super(FILE_TOOL_NAMES.LIST_FILES_IN_DIR, client);
|
|
73
|
+
}
|
|
74
|
+
getToolDescription() {
|
|
75
|
+
return {
|
|
76
|
+
name: this.name,
|
|
77
|
+
description: "Lists all files and directories that exist in a specific Obsidian directory. Returns a hierarchical structure showing files, folders, and their relationships. Useful for exploring vault organization and finding specific files.",
|
|
78
|
+
examples: [
|
|
79
|
+
{
|
|
80
|
+
description: "List files in Documents folder",
|
|
81
|
+
args: {
|
|
82
|
+
dirpath: "Documents"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
description: "Example response structure",
|
|
87
|
+
args: {
|
|
88
|
+
dirpath: "Projects"
|
|
89
|
+
},
|
|
90
|
+
response: [
|
|
91
|
+
{
|
|
92
|
+
"path": "Projects/Active",
|
|
93
|
+
"type": "folder",
|
|
94
|
+
"children": [
|
|
95
|
+
{ "path": "Projects/Active/ProjectA.md", "type": "file" },
|
|
96
|
+
{ "path": "Projects/Active/ProjectB.md", "type": "file" }
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"path": "Projects/Archive",
|
|
101
|
+
"type": "folder",
|
|
102
|
+
"children": [
|
|
103
|
+
{ "path": "Projects/Archive/OldProject.md", "type": "file" }
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: {
|
|
112
|
+
dirpath: {
|
|
113
|
+
type: "string",
|
|
114
|
+
description: "Path to list files from (relative to your vault root). Note that empty directories will not be returned.",
|
|
115
|
+
format: "path"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
required: ["dirpath"]
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async runTool(args) {
|
|
123
|
+
try {
|
|
124
|
+
logger.debug(`Listing files in directory: ${args.dirpath}`);
|
|
125
|
+
const files = await this.client.listFilesInDir(args.dirpath);
|
|
126
|
+
return this.createResponse(files);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return this.handleError(error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createFileToolHandlers } from './files/index.js';
|
|
2
|
+
import { createSearchToolHandlers } from './search/index.js';
|
|
3
|
+
import { createPropertyToolHandlers } from './properties/index.js';
|
|
4
|
+
// Export the base handler and all submodules
|
|
5
|
+
export * from './base.js';
|
|
6
|
+
export * from './files/index.js';
|
|
7
|
+
export * from './search/index.js';
|
|
8
|
+
export * from './properties/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Create all tool handlers
|
|
11
|
+
* @param client The ObsidianClient instance
|
|
12
|
+
* @returns Array of all tool handlers
|
|
13
|
+
*/
|
|
14
|
+
export function createToolHandlers(client) {
|
|
15
|
+
return [
|
|
16
|
+
...createFileToolHandlers(client),
|
|
17
|
+
...createSearchToolHandlers(client),
|
|
18
|
+
...createPropertyToolHandlers(client)
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get a tool handler map by name
|
|
23
|
+
* @param handlers Array of tool handlers
|
|
24
|
+
* @returns Map of tool names to handlers
|
|
25
|
+
*/
|
|
26
|
+
export function createToolHandlerMap(handlers) {
|
|
27
|
+
const toolHandlerMap = new Map();
|
|
28
|
+
handlers.forEach(handler => toolHandlerMap.set(handler.name, handler));
|
|
29
|
+
return toolHandlerMap;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Properties module exports
|
|
3
|
+
*/
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
export * from './manager.js';
|
|
6
|
+
export * from './tools.js';
|
|
7
|
+
import { GetPropertiesToolHandler, UpdatePropertiesToolHandler } from './tools.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create all property-related tool handlers
|
|
10
|
+
* @param client The ObsidianClient instance
|
|
11
|
+
* @returns Array of property tool handlers
|
|
12
|
+
*/
|
|
13
|
+
export function createPropertyToolHandlers(client) {
|
|
14
|
+
return [
|
|
15
|
+
new GetPropertiesToolHandler(client),
|
|
16
|
+
new UpdatePropertiesToolHandler(client)
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.js.map
|