obsidian_fetch 0.1.7 → 0.1.10
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.
- checksums.yaml +4 -4
- data/README.md +17 -19
- data/exe/obsidian_fetch +4 -4
- data/lib/obsidian_fetch/version.rb +1 -1
- data/lib/obsidian_fetch.rb +73 -63
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f1f3795373c330483a11d7c66fdb4bf44b7312a6f4065e7aefd230e9a4fe245
|
4
|
+
data.tar.gz: 8cd7c19f1780e3c9f89ca537f26ec5ad711073b7cd8e7ba07ed6a4d015b0b9e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ea95a17289bd2ec4f5d940a947abea3c458febdec89ffb7695e58d2ad4ea5cb3f281194552e56ec6ebc4c67557cf6ca12aafeab9c5aad0e2373a3b7a484ff7d
|
7
|
+
data.tar.gz: 0a089431af584dba6faeafe73b8d86f41ee2dc42bcdd5ef640e56dd65421fb539eaf8107ed4cea5421bbda397103268b234f27c043546a366a4ed9137952f776
|
data/README.md
CHANGED
@@ -1,38 +1,36 @@
|
|
1
1
|
# ObsidianFetch
|
2
2
|
|
3
|
-
|
3
|
+
MCP servers specialising in retrieving information from Obsidian vaults.
|
4
4
|
|
5
|
-
|
5
|
+
The existing MCP server has the following drawbacks:
|
6
|
+
- There are many commands, and when computational resources are limited, it can take a long time to load the prompt.
|
7
|
+
- When reading a note labeled "LLM," it is necessary to search for the path first before loading it, but the LLM may not always follow this procedure.
|
8
|
+
- Some tools have unnecessary options, causing the LLM to sometimes fail to invoke the tool correctly.
|
6
9
|
|
7
|
-
|
10
|
+
These issues become particularly noticeable when running an LLM on a local GPU.
|
11
|
+
To address this, we developed a new MCP server that simply retrieves and loads a list of notes.
|
8
12
|
|
9
|
-
|
13
|
+
Additionally, the new server has the following features:
|
14
|
+
- When the LLM tries to retrieve link information and searches with brackets like `[[link name]]`, it automatically removes characters that cannot be used in links.
|
15
|
+
- When reading a file, if there are links pointing to the opened file, it displays them.
|
16
|
+
- Especially in network-style note tools like Obsidian, following such links to load related notes can be very powerful.
|
17
|
+
- Support for aliases.
|
10
18
|
|
11
|
-
|
19
|
+
## Installation
|
12
20
|
|
13
21
|
```bash
|
14
|
-
|
22
|
+
gem install obsidian_fetch
|
15
23
|
```
|
16
24
|
|
17
|
-
|
25
|
+
## Usage
|
18
26
|
|
19
27
|
```bash
|
20
|
-
|
28
|
+
obsidian_fetch /path/to/your/vault
|
21
29
|
```
|
22
30
|
|
23
|
-
## Usage
|
24
|
-
|
25
|
-
TODO: Write usage instructions here
|
26
|
-
|
27
|
-
## Development
|
28
|
-
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake ` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
-
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
-
|
33
31
|
## Contributing
|
34
32
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
33
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/soukouki/obsidian_fetch.
|
36
34
|
|
37
35
|
## License
|
38
36
|
|
data/exe/obsidian_fetch
CHANGED
@@ -24,7 +24,7 @@ tool 'read' do
|
|
24
24
|
name = args[:name]
|
25
25
|
# 名前が文字列でない場合
|
26
26
|
next 'Name must be a string' unless name.is_a?(String)
|
27
|
-
|
27
|
+
vault.tool_read(name)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -39,7 +39,7 @@ tool 'read_multiple' do
|
|
39
39
|
# 名前が文字列の配列でない場合
|
40
40
|
next 'Name must be an array of strings' unless names.is_a?(Array) && names.all? { |name| name.is_a?(String) }
|
41
41
|
names.map do |name|
|
42
|
-
|
42
|
+
vault.tool_read(name)
|
43
43
|
end.join("\n\n---\n\n")
|
44
44
|
end
|
45
45
|
end
|
@@ -53,7 +53,7 @@ tool 'list' do
|
|
53
53
|
name = args[:name]
|
54
54
|
# 名前が文字列でない場合
|
55
55
|
next 'Name must be a string' unless name.is_a?(String)
|
56
|
-
|
56
|
+
vault.tool_list(name)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
@@ -67,7 +67,7 @@ tool 'list_multiple' do
|
|
67
67
|
# 名前が文字列の配列でない場合
|
68
68
|
next 'Name must be an array of strings' unless names.is_a?(Array) && names.all? { |name| name.is_a?(String) }
|
69
69
|
names.map do |name|
|
70
|
-
|
70
|
+
vault.tool_list(name)
|
71
71
|
end.join("\n\n---\n\n")
|
72
72
|
end
|
73
73
|
end
|
data/lib/obsidian_fetch.rb
CHANGED
@@ -127,73 +127,83 @@ module ObsidianFetch
|
|
127
127
|
file_pathes.uniq!
|
128
128
|
end
|
129
129
|
end
|
130
|
-
end
|
131
130
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
file_pathes
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
# 複数のファイルがある場合は、---とファイル名で区切って返す
|
147
|
-
file_pathes.map do |file_path|
|
148
|
-
content = open(file_path) { |f| f.read.force_encoding('UTF-8') }
|
149
|
-
link_notes = if vault.links_by_file_path[file_path].nil?
|
150
|
-
""
|
151
|
-
else
|
152
|
-
<<~EOS
|
153
|
-
This note is linked by the following notes:
|
154
|
-
#{(vault.links_by_file_path[file_path] || []).shuffle.map { |file_path| "- #{File.basename(file_path, '.md')}" }.join("\n")}
|
131
|
+
public
|
132
|
+
|
133
|
+
def tool_read name
|
134
|
+
name = Vault.normalize_note_name(name)
|
135
|
+
file_pathes = @notes[name]
|
136
|
+
# 名前のノートが存在しない場合
|
137
|
+
if file_pathes.nil?
|
138
|
+
return "Note not found: #{name}" if @links_by_file_name[name].nil?
|
139
|
+
file_pathes = @links_by_file_name[name]
|
140
|
+
return <<~EOS
|
141
|
+
Note not found: #{name}
|
142
|
+
However, I found other notes linked to this note.
|
143
|
+
#{file_pathes.map { |file_path| "- #{file_path}" }.join("\n")}
|
155
144
|
EOS
|
156
145
|
end
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
return <<~EOS unless has_found_link
|
178
|
-
Note not found: #{name}
|
179
|
-
Search again with a substring or a string with a different notation.
|
180
|
-
EOS
|
181
|
-
return <<~EOS
|
182
|
-
Note not found: #{name}
|
183
|
-
However, I found other notes linked to this note.
|
184
|
-
#{vault.links_by_file_name[name].shuffle.map { |file_path| "- #{File.basename(file_path, '.md')}" }.join("\n")}
|
185
|
-
EOS
|
146
|
+
|
147
|
+
# 複数のファイルがある場合は、---とファイル名で区切って返す
|
148
|
+
file_pathes.map do |file_path|
|
149
|
+
content = open(file_path) { |f| f.read.force_encoding('UTF-8') }
|
150
|
+
link_notes = if @links_by_file_path[file_path].nil?
|
151
|
+
""
|
152
|
+
else
|
153
|
+
<<~EOS
|
154
|
+
This note is linked by the following notes:
|
155
|
+
#{(@links_by_file_path[file_path] || []).shuffle.map { |file_path| "- #{File.basename(file_path, '.md')}" }.join("\n")}
|
156
|
+
EOS
|
157
|
+
end
|
158
|
+
preface = <<~EOS
|
159
|
+
The contents of the note '#{name}' is as follows.
|
160
|
+
#{link_notes}
|
161
|
+
---
|
162
|
+
|
163
|
+
EOS
|
164
|
+
preface + content
|
165
|
+
end.join("\n\n---\n\n")
|
186
166
|
end
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
167
|
+
|
168
|
+
MAX_LIST_SIZE = 20
|
169
|
+
def tool_list name
|
170
|
+
name = Vault.normalize_note_name(name)
|
171
|
+
split_name = name.split(/[\s ]+/)
|
172
|
+
# 空白文字で検索された場合は失敗した旨を返す
|
173
|
+
# 仮に全ノートからランダムなMAX_LIST_SIZEを返してしまうと、LLMが誤って呼び出した場合に偽の関連性を持ってしまうため
|
174
|
+
if split_name.empty?
|
175
|
+
return <<~EOS
|
176
|
+
It cannot be listed in a blank string.
|
177
|
+
EOS
|
178
|
+
end
|
179
|
+
matched_notes = @notes.select do |note_name, _file_pathes|
|
180
|
+
split_name.map {|name_part| note_name.include?(name_part) }.all?
|
181
|
+
end
|
182
|
+
# 名前で検索したが見つからない場合
|
183
|
+
if matched_notes.empty?
|
184
|
+
has_found_link = @links_by_file_name[name] && !@links_by_file_name[name].empty?
|
185
|
+
return <<~EOS unless has_found_link
|
186
|
+
Note not found: #{name}
|
187
|
+
Search again with a substring or a string with a different notation.
|
188
|
+
EOS
|
189
|
+
return <<~EOS
|
190
|
+
Note not found: #{name}
|
191
|
+
However, I found other notes linked to this note.
|
192
|
+
#{@links_by_file_name[name].shuffle.map { |file_path| "- #{File.basename(file_path, '.md')}" }.join("\n")}
|
193
|
+
EOS
|
194
|
+
end
|
195
|
+
# マッチした名前の数が多すぎる場合は、ランダムにMAX_LIST_SIZE個選ぶ
|
196
|
+
preface = "Notes matching '#{name}' are as follows.\n"
|
197
|
+
if matched_notes.size > MAX_LIST_SIZE
|
198
|
+
matched_notes = matched_notes.to_a.sample(MAX_LIST_SIZE).to_h
|
199
|
+
preface = "Too many notes matched. I will show you only #{MAX_LIST_SIZE} of them.\n" + preface
|
200
|
+
end
|
201
|
+
# マッチした名前のリストで返す
|
202
|
+
list = matched_notes.keys.shuffle.map do |note_name|
|
203
|
+
"- #{note_name}"
|
204
|
+
end.join("\n")
|
205
|
+
preface + list
|
192
206
|
end
|
193
|
-
# マッチした名前のリストで返す
|
194
|
-
list = matched_notes.keys.shuffle.map do |note_name|
|
195
|
-
"- #{note_name}"
|
196
|
-
end.join("\n")
|
197
|
-
preface + list
|
198
207
|
end
|
208
|
+
|
199
209
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: obsidian_fetch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sou7
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mcp-rb
|