booklab-mcp 0.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/LICENSE +21 -0
- package/README.md +45 -0
- package/data/book-profiles.json +1043 -0
- package/package.json +38 -0
- package/server.js +227 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Björn Röjgren
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# BookLab MCP Server
|
|
2
|
+
|
|
3
|
+
Curated nonfiction book recommendations for AI agents via the [Model Context Protocol](https://modelcontextprotocol.io).
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
// claude_desktop_config.json
|
|
9
|
+
{
|
|
10
|
+
"mcpServers": {
|
|
11
|
+
"booklab": {
|
|
12
|
+
"command": "node",
|
|
13
|
+
"args": ["/path/to/booklab-agents/server.js"]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Tools
|
|
20
|
+
|
|
21
|
+
| Tool | Description |
|
|
22
|
+
|------|-------------|
|
|
23
|
+
| `recommend` | Get ranked book recommendations by describing a situation, question, or topic |
|
|
24
|
+
| `book_profile` | Get the full structured profile of a specific book |
|
|
25
|
+
| `list_books` | List all books in the curated library |
|
|
26
|
+
|
|
27
|
+
## Resource
|
|
28
|
+
|
|
29
|
+
- `booklab://library` — Full library as JSON
|
|
30
|
+
|
|
31
|
+
## Library
|
|
32
|
+
|
|
33
|
+
21 curated nonfiction books (all 5/5 rated), covering philosophy, psychology, history, economics, and human nature.
|
|
34
|
+
|
|
35
|
+
## How It Works
|
|
36
|
+
|
|
37
|
+
The server uses TF-IDF scoring with concept expansion (synonym maps for 17 concept families) to match natural language queries against structured book profiles. Each profile includes themes, tags, key insights, emotional tone, worldview, difficulty rating, and connections to other books.
|
|
38
|
+
|
|
39
|
+
## Built By
|
|
40
|
+
|
|
41
|
+
[BookLab by Bjorn](https://booklabbybjorn.com) — 10+ years of nonfiction book reviews. 16k YouTube subscribers, 43k X followers.
|
|
42
|
+
|
|
43
|
+
## License
|
|
44
|
+
|
|
45
|
+
MIT
|
|
@@ -0,0 +1,1043 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "mans-search-for-meaning",
|
|
4
|
+
"title": "Man's Search for Meaning",
|
|
5
|
+
"author": "Viktor E. Frankl",
|
|
6
|
+
"year": 1946,
|
|
7
|
+
"rating": 5,
|
|
8
|
+
"themes": [
|
|
9
|
+
"meaning",
|
|
10
|
+
"suffering",
|
|
11
|
+
"resilience",
|
|
12
|
+
"purpose",
|
|
13
|
+
"Holocaust",
|
|
14
|
+
"logotherapy",
|
|
15
|
+
"existentialism"
|
|
16
|
+
],
|
|
17
|
+
"worldview": "Meaning can be found in any circumstance, even the worst suffering. Purpose is chosen, not given.",
|
|
18
|
+
"emotionalTone": [
|
|
19
|
+
"profound",
|
|
20
|
+
"harrowing",
|
|
21
|
+
"hopeful",
|
|
22
|
+
"contemplative"
|
|
23
|
+
],
|
|
24
|
+
"difficulty": "accessible",
|
|
25
|
+
"pageCount": 184,
|
|
26
|
+
"bestFor": [
|
|
27
|
+
"Someone going through hardship or loss",
|
|
28
|
+
"Anyone questioning the purpose of life",
|
|
29
|
+
"Understanding resilience and human psychology",
|
|
30
|
+
"Foundational existential philosophy"
|
|
31
|
+
],
|
|
32
|
+
"notFor": [
|
|
33
|
+
"Looking for practical self-help steps",
|
|
34
|
+
"Wanting light, casual reading"
|
|
35
|
+
],
|
|
36
|
+
"connections": [
|
|
37
|
+
"the-denial-of-death",
|
|
38
|
+
"12-rules-for-life",
|
|
39
|
+
"flow",
|
|
40
|
+
"lost-connections"
|
|
41
|
+
],
|
|
42
|
+
"keyInsight": "Those who have a 'why' to live can bear almost any 'how'.",
|
|
43
|
+
"bjornSays": "The most important book I've ever read. Changed how I think about suffering and meaning. Everyone should read this once.",
|
|
44
|
+
"tags": [
|
|
45
|
+
"psychology",
|
|
46
|
+
"philosophy",
|
|
47
|
+
"memoir",
|
|
48
|
+
"classic",
|
|
49
|
+
"short"
|
|
50
|
+
],
|
|
51
|
+
"asin": "0807014273",
|
|
52
|
+
"amazonUrl": "https://www.amazon.com/dp/0807014273?tag=poorbjorn-20"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "the-righteous-mind",
|
|
56
|
+
"title": "The Righteous Mind",
|
|
57
|
+
"author": "Jonathan Haidt",
|
|
58
|
+
"year": 2012,
|
|
59
|
+
"rating": 5,
|
|
60
|
+
"themes": [
|
|
61
|
+
"morality",
|
|
62
|
+
"politics",
|
|
63
|
+
"tribalism",
|
|
64
|
+
"moral psychology",
|
|
65
|
+
"intuition",
|
|
66
|
+
"reason"
|
|
67
|
+
],
|
|
68
|
+
"worldview": "Moral judgments are driven by intuition, not reason. Different moral foundations explain political divides.",
|
|
69
|
+
"emotionalTone": [
|
|
70
|
+
"eye-opening",
|
|
71
|
+
"balanced",
|
|
72
|
+
"intellectual",
|
|
73
|
+
"challenging"
|
|
74
|
+
],
|
|
75
|
+
"difficulty": "moderate",
|
|
76
|
+
"pageCount": 448,
|
|
77
|
+
"bestFor": [
|
|
78
|
+
"Understanding why people disagree politically",
|
|
79
|
+
"Moral psychology and decision-making",
|
|
80
|
+
"Anyone frustrated by political polarization",
|
|
81
|
+
"Building empathy across ideological lines"
|
|
82
|
+
],
|
|
83
|
+
"notFor": [
|
|
84
|
+
"Looking for one side to be 'right'",
|
|
85
|
+
"Wanting simple moral frameworks"
|
|
86
|
+
],
|
|
87
|
+
"connections": [
|
|
88
|
+
"sapiens",
|
|
89
|
+
"the-true-believer",
|
|
90
|
+
"spiral-dynamics",
|
|
91
|
+
"the-laws-of-human-nature"
|
|
92
|
+
],
|
|
93
|
+
"keyInsight": "The elephant (intuition) drives, the rider (reason) rationalizes. We are groupish, not just selfish.",
|
|
94
|
+
"bjornSays": "Completely rewired how I see moral disagreements. Made me more empathetic and less judgmental. Essential reading.",
|
|
95
|
+
"tags": [
|
|
96
|
+
"psychology",
|
|
97
|
+
"politics",
|
|
98
|
+
"science",
|
|
99
|
+
"morality"
|
|
100
|
+
],
|
|
101
|
+
"asin": "0307455777",
|
|
102
|
+
"amazonUrl": "https://www.amazon.com/dp/0307455777?tag=poorbjorn-20"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "sapiens",
|
|
106
|
+
"title": "Sapiens: A Brief History of Humankind",
|
|
107
|
+
"author": "Yuval Noah Harari",
|
|
108
|
+
"year": 2011,
|
|
109
|
+
"rating": 5,
|
|
110
|
+
"themes": [
|
|
111
|
+
"history",
|
|
112
|
+
"human evolution",
|
|
113
|
+
"culture",
|
|
114
|
+
"religion",
|
|
115
|
+
"capitalism",
|
|
116
|
+
"shared myths"
|
|
117
|
+
],
|
|
118
|
+
"worldview": "Human dominance comes from our ability to create and believe shared fictions — money, nations, religions.",
|
|
119
|
+
"emotionalTone": [
|
|
120
|
+
"sweeping",
|
|
121
|
+
"provocative",
|
|
122
|
+
"accessible",
|
|
123
|
+
"paradigm-shifting"
|
|
124
|
+
],
|
|
125
|
+
"difficulty": "accessible",
|
|
126
|
+
"pageCount": 464,
|
|
127
|
+
"bestFor": [
|
|
128
|
+
"Big-picture understanding of humanity",
|
|
129
|
+
"Why human societies work the way they do",
|
|
130
|
+
"Questioning assumptions about progress",
|
|
131
|
+
"First serious nonfiction book"
|
|
132
|
+
],
|
|
133
|
+
"notFor": [
|
|
134
|
+
"Wanting deep expertise on any single topic",
|
|
135
|
+
"Readers who dislike broad generalizations"
|
|
136
|
+
],
|
|
137
|
+
"connections": [
|
|
138
|
+
"the-righteous-mind",
|
|
139
|
+
"the-beginning-of-infinity",
|
|
140
|
+
"the-better-angels-of-our-nature",
|
|
141
|
+
"spiral-dynamics"
|
|
142
|
+
],
|
|
143
|
+
"keyInsight": "Homo sapiens rules the world because we are the only animal that can cooperate flexibly in large numbers through shared myths.",
|
|
144
|
+
"bjornSays": "The book that made me fall in love with big-picture thinking. Not always right, but always thought-provoking.",
|
|
145
|
+
"tags": [
|
|
146
|
+
"history",
|
|
147
|
+
"anthropology",
|
|
148
|
+
"philosophy",
|
|
149
|
+
"bestseller"
|
|
150
|
+
],
|
|
151
|
+
"asin": "0062316117",
|
|
152
|
+
"amazonUrl": "https://www.amazon.com/dp/0062316117?tag=poorbjorn-20"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "the-denial-of-death",
|
|
156
|
+
"title": "The Denial of Death",
|
|
157
|
+
"author": "Ernest Becker",
|
|
158
|
+
"year": 1973,
|
|
159
|
+
"rating": 5,
|
|
160
|
+
"themes": [
|
|
161
|
+
"death anxiety",
|
|
162
|
+
"heroism",
|
|
163
|
+
"narcissism",
|
|
164
|
+
"existentialism",
|
|
165
|
+
"terror management",
|
|
166
|
+
"meaning"
|
|
167
|
+
],
|
|
168
|
+
"worldview": "The fear of death is the primary driver of human behavior. We build heroic projects to deny our mortality.",
|
|
169
|
+
"emotionalTone": [
|
|
170
|
+
"heavy",
|
|
171
|
+
"profound",
|
|
172
|
+
"unsettling",
|
|
173
|
+
"liberating"
|
|
174
|
+
],
|
|
175
|
+
"difficulty": "challenging",
|
|
176
|
+
"pageCount": 336,
|
|
177
|
+
"bestFor": [
|
|
178
|
+
"Deep existential exploration",
|
|
179
|
+
"Understanding human motivation at its root",
|
|
180
|
+
"Readers comfortable with heavy philosophy",
|
|
181
|
+
"After reading Frankl, Camus, or Kierkegaard"
|
|
182
|
+
],
|
|
183
|
+
"notFor": [
|
|
184
|
+
"Casual readers",
|
|
185
|
+
"Anyone in a dark mental place",
|
|
186
|
+
"Wanting practical advice"
|
|
187
|
+
],
|
|
188
|
+
"connections": [
|
|
189
|
+
"mans-search-for-meaning",
|
|
190
|
+
"civilization-and-its-discontents",
|
|
191
|
+
"12-rules-for-life",
|
|
192
|
+
"notes-from-underground"
|
|
193
|
+
],
|
|
194
|
+
"keyInsight": "What we call culture is essentially a system of hero myths designed to deny death and give us a sense of cosmic significance.",
|
|
195
|
+
"bjornSays": "The hardest book I've loved. Will make you confront things you'd rather not. But you'll understand yourself and others far better.",
|
|
196
|
+
"tags": [
|
|
197
|
+
"psychology",
|
|
198
|
+
"philosophy",
|
|
199
|
+
"existentialism",
|
|
200
|
+
"Pulitzer"
|
|
201
|
+
],
|
|
202
|
+
"asin": "0684832402",
|
|
203
|
+
"amazonUrl": "https://www.amazon.com/dp/0684832402?tag=poorbjorn-20"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"id": "the-beginning-of-infinity",
|
|
207
|
+
"title": "The Beginning of Infinity",
|
|
208
|
+
"author": "David Deutsch",
|
|
209
|
+
"year": 2011,
|
|
210
|
+
"rating": 5,
|
|
211
|
+
"themes": [
|
|
212
|
+
"epistemology",
|
|
213
|
+
"progress",
|
|
214
|
+
"science",
|
|
215
|
+
"optimism",
|
|
216
|
+
"explanation",
|
|
217
|
+
"infinity"
|
|
218
|
+
],
|
|
219
|
+
"worldview": "All problems are solvable given the right knowledge. Progress is unbounded. Good explanations are the engine of civilization.",
|
|
220
|
+
"emotionalTone": [
|
|
221
|
+
"mind-expanding",
|
|
222
|
+
"optimistic",
|
|
223
|
+
"dense",
|
|
224
|
+
"exhilarating"
|
|
225
|
+
],
|
|
226
|
+
"difficulty": "challenging",
|
|
227
|
+
"pageCount": 496,
|
|
228
|
+
"bestFor": [
|
|
229
|
+
"Rethinking the nature of knowledge and progress",
|
|
230
|
+
"Rational optimism backed by deep philosophy",
|
|
231
|
+
"Scientists, builders, and thinkers",
|
|
232
|
+
"Anyone tired of doom narratives"
|
|
233
|
+
],
|
|
234
|
+
"notFor": [
|
|
235
|
+
"Light reading",
|
|
236
|
+
"Wanting quick takeaways",
|
|
237
|
+
"Readers who prefer narrative over argument"
|
|
238
|
+
],
|
|
239
|
+
"connections": [
|
|
240
|
+
"sapiens",
|
|
241
|
+
"the-better-angels-of-our-nature",
|
|
242
|
+
"the-almanack-of-naval"
|
|
243
|
+
],
|
|
244
|
+
"keyInsight": "Problems are inevitable. Problems are soluble. The only thing that can limit progress is a failure to seek good explanations.",
|
|
245
|
+
"bjornSays": "The most optimistic book I've ever read — and it earns every ounce of that optimism. Changed my entire worldview.",
|
|
246
|
+
"tags": [
|
|
247
|
+
"philosophy",
|
|
248
|
+
"science",
|
|
249
|
+
"epistemology",
|
|
250
|
+
"optimism"
|
|
251
|
+
],
|
|
252
|
+
"asin": "0143121359",
|
|
253
|
+
"amazonUrl": "https://www.amazon.com/dp/0143121359?tag=poorbjorn-20"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"id": "flow",
|
|
257
|
+
"title": "Flow: The Psychology of Optimal Experience",
|
|
258
|
+
"author": "Mihaly Csikszentmihalyi",
|
|
259
|
+
"year": 1990,
|
|
260
|
+
"rating": 5,
|
|
261
|
+
"themes": [
|
|
262
|
+
"flow state",
|
|
263
|
+
"happiness",
|
|
264
|
+
"creativity",
|
|
265
|
+
"psychology",
|
|
266
|
+
"optimal experience",
|
|
267
|
+
"engagement"
|
|
268
|
+
],
|
|
269
|
+
"worldview": "Happiness is not something that happens to you — it's a state you create through focused engagement with challenging tasks.",
|
|
270
|
+
"emotionalTone": [
|
|
271
|
+
"inspiring",
|
|
272
|
+
"practical",
|
|
273
|
+
"intellectual",
|
|
274
|
+
"uplifting"
|
|
275
|
+
],
|
|
276
|
+
"difficulty": "accessible",
|
|
277
|
+
"pageCount": 303,
|
|
278
|
+
"bestFor": [
|
|
279
|
+
"Understanding what makes life satisfying",
|
|
280
|
+
"Improving focus and engagement at work",
|
|
281
|
+
"The science behind being 'in the zone'",
|
|
282
|
+
"Artists, athletes, and knowledge workers"
|
|
283
|
+
],
|
|
284
|
+
"notFor": [
|
|
285
|
+
"Wanting quick productivity hacks",
|
|
286
|
+
"Expecting a memoir or narrative"
|
|
287
|
+
],
|
|
288
|
+
"connections": [
|
|
289
|
+
"mans-search-for-meaning",
|
|
290
|
+
"deep-work",
|
|
291
|
+
"the-almanack-of-naval"
|
|
292
|
+
],
|
|
293
|
+
"keyInsight": "The best moments in life occur when body or mind is stretched to its limits in voluntary effort to accomplish something difficult and worthwhile.",
|
|
294
|
+
"bjornSays": "The definitive book on what makes life feel worth living. Changed how I think about work, hobbies, and happiness.",
|
|
295
|
+
"tags": [
|
|
296
|
+
"psychology",
|
|
297
|
+
"happiness",
|
|
298
|
+
"performance",
|
|
299
|
+
"classic"
|
|
300
|
+
],
|
|
301
|
+
"asin": "0061339202",
|
|
302
|
+
"amazonUrl": "https://www.amazon.com/dp/0061339202?tag=poorbjorn-20"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"id": "stoner",
|
|
306
|
+
"title": "Stoner",
|
|
307
|
+
"author": "John Williams",
|
|
308
|
+
"year": 1965,
|
|
309
|
+
"rating": 5,
|
|
310
|
+
"themes": [
|
|
311
|
+
"quiet life",
|
|
312
|
+
"academia",
|
|
313
|
+
"love",
|
|
314
|
+
"duty",
|
|
315
|
+
"resilience",
|
|
316
|
+
"meaning in ordinary life"
|
|
317
|
+
],
|
|
318
|
+
"worldview": "A life doesn't need to be extraordinary to be profound. Dignity is found in persistence and quiet devotion.",
|
|
319
|
+
"emotionalTone": [
|
|
320
|
+
"melancholic",
|
|
321
|
+
"beautiful",
|
|
322
|
+
"quiet",
|
|
323
|
+
"devastating"
|
|
324
|
+
],
|
|
325
|
+
"difficulty": "accessible",
|
|
326
|
+
"pageCount": 278,
|
|
327
|
+
"bestFor": [
|
|
328
|
+
"Readers who appreciate literary fiction",
|
|
329
|
+
"Anyone feeling their life is 'ordinary'",
|
|
330
|
+
"Understanding the beauty of an unremarkable life",
|
|
331
|
+
"After reading Dostoevsky or Camus"
|
|
332
|
+
],
|
|
333
|
+
"notFor": [
|
|
334
|
+
"Wanting action or plot twists",
|
|
335
|
+
"Looking for self-help or practical takeaways"
|
|
336
|
+
],
|
|
337
|
+
"connections": [
|
|
338
|
+
"mans-search-for-meaning",
|
|
339
|
+
"notes-from-underground"
|
|
340
|
+
],
|
|
341
|
+
"keyInsight": "The quiet, stubborn persistence of an ordinary man through an ordinary life can be the most moving story ever told.",
|
|
342
|
+
"bjornSays": "The most beautiful novel I've ever read. It wrecked me. A masterpiece about the dignity of an ordinary life.",
|
|
343
|
+
"tags": [
|
|
344
|
+
"fiction",
|
|
345
|
+
"literary",
|
|
346
|
+
"classic",
|
|
347
|
+
"quiet"
|
|
348
|
+
],
|
|
349
|
+
"asin": "1590171993",
|
|
350
|
+
"amazonUrl": "https://www.amazon.com/dp/1590171993?tag=poorbjorn-20"
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"id": "the-true-believer",
|
|
354
|
+
"title": "The True Believer",
|
|
355
|
+
"author": "Eric Hoffer",
|
|
356
|
+
"year": 1951,
|
|
357
|
+
"rating": 5,
|
|
358
|
+
"themes": [
|
|
359
|
+
"mass movements",
|
|
360
|
+
"fanaticism",
|
|
361
|
+
"identity",
|
|
362
|
+
"frustration",
|
|
363
|
+
"propaganda",
|
|
364
|
+
"conformity"
|
|
365
|
+
],
|
|
366
|
+
"worldview": "Mass movements attract the frustrated and self-loathing. The fanatic flees the self by merging with a holy cause.",
|
|
367
|
+
"emotionalTone": [
|
|
368
|
+
"sharp",
|
|
369
|
+
"prophetic",
|
|
370
|
+
"disturbing",
|
|
371
|
+
"concise"
|
|
372
|
+
],
|
|
373
|
+
"difficulty": "moderate",
|
|
374
|
+
"pageCount": 176,
|
|
375
|
+
"bestFor": [
|
|
376
|
+
"Understanding radicalization and extremism",
|
|
377
|
+
"Why people join movements and cults",
|
|
378
|
+
"Political psychology",
|
|
379
|
+
"Anyone watching populism rise"
|
|
380
|
+
],
|
|
381
|
+
"notFor": [
|
|
382
|
+
"Wanting nuance about specific movements",
|
|
383
|
+
"Looking for solutions, not diagnosis"
|
|
384
|
+
],
|
|
385
|
+
"connections": [
|
|
386
|
+
"the-righteous-mind",
|
|
387
|
+
"sapiens",
|
|
388
|
+
"spiral-dynamics"
|
|
389
|
+
],
|
|
390
|
+
"keyInsight": "A mass movement attracts and holds a following not by doctrine but by the refuge it offers from the anxieties of an empty life.",
|
|
391
|
+
"bjornSays": "Written in 1951, reads like it was written yesterday. Eerily accurate about why people radicalize. Short, dense, brilliant.",
|
|
392
|
+
"tags": [
|
|
393
|
+
"psychology",
|
|
394
|
+
"politics",
|
|
395
|
+
"sociology",
|
|
396
|
+
"classic",
|
|
397
|
+
"short"
|
|
398
|
+
],
|
|
399
|
+
"asin": "0060505915",
|
|
400
|
+
"amazonUrl": "https://www.amazon.com/dp/0060505915?tag=poorbjorn-20"
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"id": "top-five-regrets-of-the-dying",
|
|
404
|
+
"title": "The Top Five Regrets of the Dying",
|
|
405
|
+
"author": "Bronnie Ware",
|
|
406
|
+
"year": 2012,
|
|
407
|
+
"rating": 5,
|
|
408
|
+
"themes": [
|
|
409
|
+
"death",
|
|
410
|
+
"regret",
|
|
411
|
+
"authenticity",
|
|
412
|
+
"courage",
|
|
413
|
+
"relationships",
|
|
414
|
+
"palliative care"
|
|
415
|
+
],
|
|
416
|
+
"worldview": "The dying consistently regret the same things: not living authentically, working too hard, suppressing feelings, losing touch with friends, and not choosing happiness.",
|
|
417
|
+
"emotionalTone": [
|
|
418
|
+
"moving",
|
|
419
|
+
"sobering",
|
|
420
|
+
"gentle",
|
|
421
|
+
"life-changing"
|
|
422
|
+
],
|
|
423
|
+
"difficulty": "accessible",
|
|
424
|
+
"pageCount": 299,
|
|
425
|
+
"bestFor": [
|
|
426
|
+
"Anyone at a life crossroads",
|
|
427
|
+
"Perspective on what truly matters",
|
|
428
|
+
"Motivation to live more authentically",
|
|
429
|
+
"Pairs well with Stoic philosophy"
|
|
430
|
+
],
|
|
431
|
+
"notFor": [
|
|
432
|
+
"Wanting rigorous research",
|
|
433
|
+
"Anyone recently bereaved (may be too raw)"
|
|
434
|
+
],
|
|
435
|
+
"connections": [
|
|
436
|
+
"mans-search-for-meaning",
|
|
437
|
+
"the-denial-of-death",
|
|
438
|
+
"12-rules-for-life"
|
|
439
|
+
],
|
|
440
|
+
"keyInsight": "The number one regret: 'I wish I'd had the courage to live a life true to myself, not the life others expected of me.'",
|
|
441
|
+
"bjornSays": "Simple but devastating. Read it once a year. It realigns your priorities like nothing else.",
|
|
442
|
+
"tags": [
|
|
443
|
+
"memoir",
|
|
444
|
+
"self-help",
|
|
445
|
+
"death",
|
|
446
|
+
"wisdom"
|
|
447
|
+
],
|
|
448
|
+
"asin": "1401956009",
|
|
449
|
+
"amazonUrl": "https://www.amazon.com/dp/1401956009?tag=poorbjorn-20"
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"id": "notes-from-underground",
|
|
453
|
+
"title": "Notes from Underground",
|
|
454
|
+
"author": "Fyodor Dostoevsky",
|
|
455
|
+
"year": 1864,
|
|
456
|
+
"rating": 5,
|
|
457
|
+
"themes": [
|
|
458
|
+
"alienation",
|
|
459
|
+
"free will",
|
|
460
|
+
"rationality",
|
|
461
|
+
"spite",
|
|
462
|
+
"consciousness",
|
|
463
|
+
"modernity"
|
|
464
|
+
],
|
|
465
|
+
"worldview": "Humans are irrational, spiteful, and will act against their own interest just to assert free will. Reason alone cannot explain us.",
|
|
466
|
+
"emotionalTone": [
|
|
467
|
+
"dark",
|
|
468
|
+
"uncomfortable",
|
|
469
|
+
"brilliant",
|
|
470
|
+
"claustrophobic"
|
|
471
|
+
],
|
|
472
|
+
"difficulty": "moderate",
|
|
473
|
+
"pageCount": 136,
|
|
474
|
+
"bestFor": [
|
|
475
|
+
"Entry point to Dostoevsky",
|
|
476
|
+
"Understanding existentialism's roots",
|
|
477
|
+
"Anyone who feels like an outsider",
|
|
478
|
+
"Philosophy of consciousness and free will"
|
|
479
|
+
],
|
|
480
|
+
"notFor": [
|
|
481
|
+
"Wanting feel-good reading",
|
|
482
|
+
"Expecting a traditional plot"
|
|
483
|
+
],
|
|
484
|
+
"connections": [
|
|
485
|
+
"the-denial-of-death",
|
|
486
|
+
"stoner",
|
|
487
|
+
"civilization-and-its-discontents"
|
|
488
|
+
],
|
|
489
|
+
"keyInsight": "Man will deliberately go mad in order to be free of the tyranny of reason.",
|
|
490
|
+
"bjornSays": "The first great existential scream. Short, furious, and uncomfortably relatable. Dostoevsky saw us coming 160 years ago.",
|
|
491
|
+
"tags": [
|
|
492
|
+
"fiction",
|
|
493
|
+
"philosophy",
|
|
494
|
+
"existentialism",
|
|
495
|
+
"classic",
|
|
496
|
+
"short"
|
|
497
|
+
],
|
|
498
|
+
"asin": "0679734520",
|
|
499
|
+
"amazonUrl": "https://www.amazon.com/dp/0679734520?tag=poorbjorn-20"
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
"id": "among-the-thugs",
|
|
503
|
+
"title": "Among the Thugs",
|
|
504
|
+
"author": "Bill Buford",
|
|
505
|
+
"year": 1991,
|
|
506
|
+
"rating": 5,
|
|
507
|
+
"themes": [
|
|
508
|
+
"violence",
|
|
509
|
+
"tribalism",
|
|
510
|
+
"mob psychology",
|
|
511
|
+
"football hooliganism",
|
|
512
|
+
"masculinity",
|
|
513
|
+
"crowd behavior"
|
|
514
|
+
],
|
|
515
|
+
"worldview": "Violence is intoxicating. The crowd experience unlocks something primal that civilization only barely suppresses.",
|
|
516
|
+
"emotionalTone": [
|
|
517
|
+
"visceral",
|
|
518
|
+
"thrilling",
|
|
519
|
+
"disturbing",
|
|
520
|
+
"honest"
|
|
521
|
+
],
|
|
522
|
+
"difficulty": "accessible",
|
|
523
|
+
"pageCount": 317,
|
|
524
|
+
"bestFor": [
|
|
525
|
+
"Understanding mob mentality and violence",
|
|
526
|
+
"Immersive journalism at its best",
|
|
527
|
+
"The dark side of tribalism",
|
|
528
|
+
"Football culture and masculinity"
|
|
529
|
+
],
|
|
530
|
+
"notFor": [
|
|
531
|
+
"Sensitive to graphic violence",
|
|
532
|
+
"Wanting academic analysis"
|
|
533
|
+
],
|
|
534
|
+
"connections": [
|
|
535
|
+
"the-true-believer",
|
|
536
|
+
"the-righteous-mind",
|
|
537
|
+
"sapiens"
|
|
538
|
+
],
|
|
539
|
+
"keyInsight": "The violence isn't the point — the belonging is. The violence is just the price of admission to something ecstatic.",
|
|
540
|
+
"bjornSays": "Jaw-dropping gonzo journalism. Buford embedded with English football hooligans and came back with one of the most honest books about human nature I've read.",
|
|
541
|
+
"tags": [
|
|
542
|
+
"journalism",
|
|
543
|
+
"sociology",
|
|
544
|
+
"sports",
|
|
545
|
+
"violence"
|
|
546
|
+
],
|
|
547
|
+
"asin": "0679745351",
|
|
548
|
+
"amazonUrl": "https://www.amazon.com/dp/0679745351?tag=poorbjorn-20"
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"id": "lost-connections",
|
|
552
|
+
"title": "Lost Connections",
|
|
553
|
+
"author": "Johann Hari",
|
|
554
|
+
"year": 2018,
|
|
555
|
+
"rating": 5,
|
|
556
|
+
"themes": [
|
|
557
|
+
"depression",
|
|
558
|
+
"connection",
|
|
559
|
+
"meaning",
|
|
560
|
+
"society",
|
|
561
|
+
"mental health",
|
|
562
|
+
"loneliness"
|
|
563
|
+
],
|
|
564
|
+
"worldview": "Depression and anxiety are largely caused by disconnection — from people, meaning, nature, and status — not just brain chemistry.",
|
|
565
|
+
"emotionalTone": [
|
|
566
|
+
"compassionate",
|
|
567
|
+
"revelatory",
|
|
568
|
+
"hopeful",
|
|
569
|
+
"personal"
|
|
570
|
+
],
|
|
571
|
+
"difficulty": "accessible",
|
|
572
|
+
"pageCount": 321,
|
|
573
|
+
"bestFor": [
|
|
574
|
+
"Understanding depression beyond the chemical model",
|
|
575
|
+
"Anyone feeling disconnected or lost",
|
|
576
|
+
"Mental health without the clinical jargon",
|
|
577
|
+
"Societal causes of unhappiness"
|
|
578
|
+
],
|
|
579
|
+
"notFor": [
|
|
580
|
+
"Wanting clinical/medical advice",
|
|
581
|
+
"Already deep into psychiatric literature"
|
|
582
|
+
],
|
|
583
|
+
"connections": [
|
|
584
|
+
"mans-search-for-meaning",
|
|
585
|
+
"when-the-body-says-no",
|
|
586
|
+
"flow"
|
|
587
|
+
],
|
|
588
|
+
"keyInsight": "You're not broken. Your pain makes sense. Depression is often a signal that core human needs are unmet.",
|
|
589
|
+
"bjornSays": "The book I wish existed when I was younger. Reframes depression from 'broken brain' to 'unmet needs.' Powerful and humane.",
|
|
590
|
+
"tags": [
|
|
591
|
+
"psychology",
|
|
592
|
+
"mental-health",
|
|
593
|
+
"society",
|
|
594
|
+
"science"
|
|
595
|
+
],
|
|
596
|
+
"asin": "163286830X",
|
|
597
|
+
"amazonUrl": "https://www.amazon.com/dp/163286830X?tag=poorbjorn-20"
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
"id": "the-laws-of-human-nature",
|
|
601
|
+
"title": "The Laws of Human Nature",
|
|
602
|
+
"author": "Robert Greene",
|
|
603
|
+
"year": 2018,
|
|
604
|
+
"rating": 5,
|
|
605
|
+
"themes": [
|
|
606
|
+
"human nature",
|
|
607
|
+
"psychology",
|
|
608
|
+
"power",
|
|
609
|
+
"narcissism",
|
|
610
|
+
"empathy",
|
|
611
|
+
"influence",
|
|
612
|
+
"self-awareness"
|
|
613
|
+
],
|
|
614
|
+
"worldview": "Human behavior follows predictable patterns rooted in evolution. Understanding these patterns is the key to mastering yourself and navigating others.",
|
|
615
|
+
"emotionalTone": [
|
|
616
|
+
"strategic",
|
|
617
|
+
"deep",
|
|
618
|
+
"unflinching",
|
|
619
|
+
"empowering"
|
|
620
|
+
],
|
|
621
|
+
"difficulty": "moderate",
|
|
622
|
+
"pageCount": 624,
|
|
623
|
+
"bestFor": [
|
|
624
|
+
"Deep understanding of why people behave as they do",
|
|
625
|
+
"Self-awareness and emotional mastery",
|
|
626
|
+
"Leadership and interpersonal dynamics",
|
|
627
|
+
"After reading 48 Laws of Power"
|
|
628
|
+
],
|
|
629
|
+
"notFor": [
|
|
630
|
+
"Short attention spans (it's 600+ pages)",
|
|
631
|
+
"Wanting warm, fuzzy psychology"
|
|
632
|
+
],
|
|
633
|
+
"connections": [
|
|
634
|
+
"the-righteous-mind",
|
|
635
|
+
"the-true-believer",
|
|
636
|
+
"the-denial-of-death",
|
|
637
|
+
"sapiens"
|
|
638
|
+
],
|
|
639
|
+
"keyInsight": "We are all more irrational, envious, and narcissistic than we realize. Self-awareness begins with accepting this.",
|
|
640
|
+
"bjornSays": "Greene's masterpiece. Dense but worth every page. Made me understand people — including myself — at a much deeper level.",
|
|
641
|
+
"tags": [
|
|
642
|
+
"psychology",
|
|
643
|
+
"self-improvement",
|
|
644
|
+
"strategy",
|
|
645
|
+
"human-nature"
|
|
646
|
+
],
|
|
647
|
+
"asin": "0525428143",
|
|
648
|
+
"amazonUrl": "https://www.amazon.com/dp/0525428143?tag=poorbjorn-20"
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
"id": "12-rules-for-life",
|
|
652
|
+
"title": "12 Rules for Life",
|
|
653
|
+
"author": "Jordan B. Peterson",
|
|
654
|
+
"year": 2018,
|
|
655
|
+
"rating": 5,
|
|
656
|
+
"themes": [
|
|
657
|
+
"responsibility",
|
|
658
|
+
"meaning",
|
|
659
|
+
"order",
|
|
660
|
+
"chaos",
|
|
661
|
+
"mythology",
|
|
662
|
+
"suffering",
|
|
663
|
+
"growth"
|
|
664
|
+
],
|
|
665
|
+
"worldview": "Life is suffering. Meaning is the antidote. Take responsibility, stand up straight, and aim at the highest good you can conceive.",
|
|
666
|
+
"emotionalTone": [
|
|
667
|
+
"intense",
|
|
668
|
+
"challenging",
|
|
669
|
+
"mythological",
|
|
670
|
+
"personal"
|
|
671
|
+
],
|
|
672
|
+
"difficulty": "moderate",
|
|
673
|
+
"pageCount": 409,
|
|
674
|
+
"bestFor": [
|
|
675
|
+
"Young men looking for direction",
|
|
676
|
+
"Understanding the role of responsibility in meaning",
|
|
677
|
+
"Mythology and psychology intersecting",
|
|
678
|
+
"Anyone feeling lost or nihilistic"
|
|
679
|
+
],
|
|
680
|
+
"notFor": [
|
|
681
|
+
"Already dismissive of Peterson (you won't engage honestly)",
|
|
682
|
+
"Wanting light, easy reading"
|
|
683
|
+
],
|
|
684
|
+
"connections": [
|
|
685
|
+
"mans-search-for-meaning",
|
|
686
|
+
"the-denial-of-death",
|
|
687
|
+
"top-five-regrets-of-the-dying"
|
|
688
|
+
],
|
|
689
|
+
"keyInsight": "Set your house in perfect order before you criticize the world. Pursue meaning, not happiness.",
|
|
690
|
+
"bjornSays": "Love him or hate him, this book genuinely helps people. The chapters on suffering and meaning are world-class.",
|
|
691
|
+
"tags": [
|
|
692
|
+
"psychology",
|
|
693
|
+
"philosophy",
|
|
694
|
+
"self-improvement",
|
|
695
|
+
"mythology"
|
|
696
|
+
],
|
|
697
|
+
"asin": "0345816021",
|
|
698
|
+
"amazonUrl": "https://www.amazon.com/dp/0345816021?tag=poorbjorn-20"
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"id": "the-almanack-of-naval",
|
|
702
|
+
"title": "The Almanack of Naval Ravikant",
|
|
703
|
+
"author": "Eric Jorgenson",
|
|
704
|
+
"year": 2020,
|
|
705
|
+
"rating": 5,
|
|
706
|
+
"themes": [
|
|
707
|
+
"wealth",
|
|
708
|
+
"happiness",
|
|
709
|
+
"leverage",
|
|
710
|
+
"philosophy",
|
|
711
|
+
"entrepreneurship",
|
|
712
|
+
"wisdom"
|
|
713
|
+
],
|
|
714
|
+
"worldview": "Seek wealth through leverage (code, media, capital), not time. Happiness is a skill, not a destination. Think from first principles.",
|
|
715
|
+
"emotionalTone": [
|
|
716
|
+
"clear",
|
|
717
|
+
"liberating",
|
|
718
|
+
"practical",
|
|
719
|
+
"philosophical"
|
|
720
|
+
],
|
|
721
|
+
"difficulty": "accessible",
|
|
722
|
+
"pageCount": 242,
|
|
723
|
+
"bestFor": [
|
|
724
|
+
"Entrepreneurs and builders",
|
|
725
|
+
"Understanding wealth creation in the internet age",
|
|
726
|
+
"Philosophical approach to happiness",
|
|
727
|
+
"Anyone who likes distilled wisdom"
|
|
728
|
+
],
|
|
729
|
+
"notFor": [
|
|
730
|
+
"Wanting step-by-step business advice",
|
|
731
|
+
"Deep academic philosophy"
|
|
732
|
+
],
|
|
733
|
+
"connections": [
|
|
734
|
+
"the-beginning-of-infinity",
|
|
735
|
+
"flow",
|
|
736
|
+
"sapiens"
|
|
737
|
+
],
|
|
738
|
+
"keyInsight": "Arm yourself with specific knowledge, accountability, and leverage. Code and media are permissionless leverage.",
|
|
739
|
+
"bjornSays": "The most quotable book I've read. Naval's thinking on wealth and happiness is razor-sharp. Free to read online, too.",
|
|
740
|
+
"tags": [
|
|
741
|
+
"business",
|
|
742
|
+
"philosophy",
|
|
743
|
+
"wisdom",
|
|
744
|
+
"startup"
|
|
745
|
+
],
|
|
746
|
+
"asin": "1544514212",
|
|
747
|
+
"amazonUrl": "https://www.amazon.com/dp/1544514212?tag=poorbjorn-20"
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
"id": "when-the-body-says-no",
|
|
751
|
+
"title": "When the Body Says No",
|
|
752
|
+
"author": "Gabor Maté",
|
|
753
|
+
"year": 2003,
|
|
754
|
+
"rating": 5,
|
|
755
|
+
"themes": [
|
|
756
|
+
"stress",
|
|
757
|
+
"disease",
|
|
758
|
+
"trauma",
|
|
759
|
+
"mind-body connection",
|
|
760
|
+
"repression",
|
|
761
|
+
"autoimmune"
|
|
762
|
+
],
|
|
763
|
+
"worldview": "Chronic stress and emotional repression don't just make you unhappy — they make you sick. The body keeps the score.",
|
|
764
|
+
"emotionalTone": [
|
|
765
|
+
"eye-opening",
|
|
766
|
+
"sobering",
|
|
767
|
+
"compassionate",
|
|
768
|
+
"scientific"
|
|
769
|
+
],
|
|
770
|
+
"difficulty": "accessible",
|
|
771
|
+
"pageCount": 320,
|
|
772
|
+
"bestFor": [
|
|
773
|
+
"Understanding the stress-disease connection",
|
|
774
|
+
"People-pleasers and chronic overachievers",
|
|
775
|
+
"Anyone with autoimmune or chronic illness",
|
|
776
|
+
"Gabor Maté's best entry point"
|
|
777
|
+
],
|
|
778
|
+
"notFor": [
|
|
779
|
+
"Wanting a quick fix for health issues",
|
|
780
|
+
"Skeptical of mind-body connections"
|
|
781
|
+
],
|
|
782
|
+
"connections": [
|
|
783
|
+
"lost-connections",
|
|
784
|
+
"mans-search-for-meaning",
|
|
785
|
+
"the-denial-of-death"
|
|
786
|
+
],
|
|
787
|
+
"keyInsight": "When we chronically repress our emotions to maintain relationships or meet expectations, the body eventually says no for us — through illness.",
|
|
788
|
+
"bjornSays": "Maté changed how I think about health. This book connects the dots between emotional patterns and physical disease. Essential.",
|
|
789
|
+
"tags": [
|
|
790
|
+
"health",
|
|
791
|
+
"psychology",
|
|
792
|
+
"science",
|
|
793
|
+
"trauma"
|
|
794
|
+
],
|
|
795
|
+
"asin": "0470923350",
|
|
796
|
+
"amazonUrl": "https://www.amazon.com/dp/0470923350?tag=poorbjorn-20"
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
"id": "determined",
|
|
800
|
+
"title": "Determined: A Science of Life Without Free Will",
|
|
801
|
+
"author": "Robert Sapolsky",
|
|
802
|
+
"year": 2023,
|
|
803
|
+
"rating": 5,
|
|
804
|
+
"themes": [
|
|
805
|
+
"free will",
|
|
806
|
+
"determinism",
|
|
807
|
+
"neuroscience",
|
|
808
|
+
"justice",
|
|
809
|
+
"behavior",
|
|
810
|
+
"biology"
|
|
811
|
+
],
|
|
812
|
+
"worldview": "Free will is an illusion. Every action is the result of biology, environment, and prior causes. This should make us more compassionate, not less.",
|
|
813
|
+
"emotionalTone": [
|
|
814
|
+
"provocative",
|
|
815
|
+
"rigorous",
|
|
816
|
+
"humbling",
|
|
817
|
+
"compassionate"
|
|
818
|
+
],
|
|
819
|
+
"difficulty": "challenging",
|
|
820
|
+
"pageCount": 528,
|
|
821
|
+
"bestFor": [
|
|
822
|
+
"The free will debate, taken seriously",
|
|
823
|
+
"Neuroscience of behavior and decision-making",
|
|
824
|
+
"After reading Behave by Sapolsky",
|
|
825
|
+
"Anyone interested in criminal justice reform"
|
|
826
|
+
],
|
|
827
|
+
"notFor": [
|
|
828
|
+
"Wanting a comforting conclusion",
|
|
829
|
+
"Light reading"
|
|
830
|
+
],
|
|
831
|
+
"connections": [
|
|
832
|
+
"notes-from-underground",
|
|
833
|
+
"the-righteous-mind",
|
|
834
|
+
"sapiens"
|
|
835
|
+
],
|
|
836
|
+
"keyInsight": "You can't show me a neuron, hormone, gene, or childhood experience that caused a behavior AND also claim the person 'freely chose' it.",
|
|
837
|
+
"bjornSays": "Sapolsky's magnum opus. Destroyed my belief in free will and somehow made me a kinder person. Dense but transformative.",
|
|
838
|
+
"tags": [
|
|
839
|
+
"neuroscience",
|
|
840
|
+
"philosophy",
|
|
841
|
+
"science",
|
|
842
|
+
"free-will"
|
|
843
|
+
],
|
|
844
|
+
"asin": "0525560971",
|
|
845
|
+
"amazonUrl": "https://www.amazon.com/dp/0525560971?tag=poorbjorn-20"
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
"id": "civilization-and-its-discontents",
|
|
849
|
+
"title": "Civilization and Its Discontents",
|
|
850
|
+
"author": "Sigmund Freud",
|
|
851
|
+
"year": 1930,
|
|
852
|
+
"rating": 5,
|
|
853
|
+
"themes": [
|
|
854
|
+
"civilization",
|
|
855
|
+
"instinct",
|
|
856
|
+
"aggression",
|
|
857
|
+
"guilt",
|
|
858
|
+
"repression",
|
|
859
|
+
"happiness"
|
|
860
|
+
],
|
|
861
|
+
"worldview": "Civilization requires the suppression of our deepest instincts. The price of social order is individual unhappiness.",
|
|
862
|
+
"emotionalTone": [
|
|
863
|
+
"dark",
|
|
864
|
+
"brilliant",
|
|
865
|
+
"pessimistic",
|
|
866
|
+
"foundational"
|
|
867
|
+
],
|
|
868
|
+
"difficulty": "moderate",
|
|
869
|
+
"pageCount": 127,
|
|
870
|
+
"bestFor": [
|
|
871
|
+
"Understanding the tension between individual and society",
|
|
872
|
+
"Foundational psychoanalytic thinking",
|
|
873
|
+
"Philosophy of civilization",
|
|
874
|
+
"Pairs with Dostoevsky and Becker"
|
|
875
|
+
],
|
|
876
|
+
"notFor": [
|
|
877
|
+
"Wanting modern, evidence-based psychology",
|
|
878
|
+
"Looking for solutions"
|
|
879
|
+
],
|
|
880
|
+
"connections": [
|
|
881
|
+
"the-denial-of-death",
|
|
882
|
+
"notes-from-underground",
|
|
883
|
+
"sapiens"
|
|
884
|
+
],
|
|
885
|
+
"keyInsight": "The price we pay for civilization is a perpetual sense of guilt and the renunciation of instinctual desires.",
|
|
886
|
+
"bjornSays": "Freud at his most accessible and profound. Short, punchy, and still relevant 95 years later.",
|
|
887
|
+
"tags": [
|
|
888
|
+
"psychology",
|
|
889
|
+
"philosophy",
|
|
890
|
+
"classic",
|
|
891
|
+
"short"
|
|
892
|
+
],
|
|
893
|
+
"asin": "0393304515",
|
|
894
|
+
"amazonUrl": "https://www.amazon.com/dp/0393304515?tag=poorbjorn-20"
|
|
895
|
+
},
|
|
896
|
+
{
|
|
897
|
+
"id": "the-better-angels-of-our-nature",
|
|
898
|
+
"title": "The Better Angels of Our Nature",
|
|
899
|
+
"author": "Steven Pinker",
|
|
900
|
+
"year": 2011,
|
|
901
|
+
"rating": 5,
|
|
902
|
+
"themes": [
|
|
903
|
+
"violence",
|
|
904
|
+
"progress",
|
|
905
|
+
"history",
|
|
906
|
+
"reason",
|
|
907
|
+
"empathy",
|
|
908
|
+
"civilization"
|
|
909
|
+
],
|
|
910
|
+
"worldview": "Violence has declined dramatically over human history. Reason, empathy, commerce, and the state have made us more peaceful.",
|
|
911
|
+
"emotionalTone": [
|
|
912
|
+
"data-heavy",
|
|
913
|
+
"optimistic",
|
|
914
|
+
"sweeping",
|
|
915
|
+
"convincing"
|
|
916
|
+
],
|
|
917
|
+
"difficulty": "challenging",
|
|
918
|
+
"pageCount": 832,
|
|
919
|
+
"bestFor": [
|
|
920
|
+
"Evidence-based optimism about humanity",
|
|
921
|
+
"Understanding the decline of violence",
|
|
922
|
+
"Big-picture history with data",
|
|
923
|
+
"Counter-narrative to doom and gloom"
|
|
924
|
+
],
|
|
925
|
+
"notFor": [
|
|
926
|
+
"Short attention spans (800+ pages)",
|
|
927
|
+
"Wanting quick reads"
|
|
928
|
+
],
|
|
929
|
+
"connections": [
|
|
930
|
+
"sapiens",
|
|
931
|
+
"the-beginning-of-infinity",
|
|
932
|
+
"the-righteous-mind"
|
|
933
|
+
],
|
|
934
|
+
"keyInsight": "We are living in the most peaceful era in human history, and the data overwhelmingly supports this despite what the news suggests.",
|
|
935
|
+
"bjornSays": "800 pages of proof that the world is getting better. Dense but essential. Pinker at his absolute best.",
|
|
936
|
+
"tags": [
|
|
937
|
+
"history",
|
|
938
|
+
"psychology",
|
|
939
|
+
"science",
|
|
940
|
+
"optimism"
|
|
941
|
+
],
|
|
942
|
+
"asin": "0143122010",
|
|
943
|
+
"amazonUrl": "https://www.amazon.com/dp/0143122010?tag=poorbjorn-20"
|
|
944
|
+
},
|
|
945
|
+
{
|
|
946
|
+
"id": "spiral-dynamics",
|
|
947
|
+
"title": "Spiral Dynamics",
|
|
948
|
+
"author": "Don Edward Beck & Christopher Cowan",
|
|
949
|
+
"year": 1996,
|
|
950
|
+
"rating": 5,
|
|
951
|
+
"themes": [
|
|
952
|
+
"developmental psychology",
|
|
953
|
+
"values",
|
|
954
|
+
"culture",
|
|
955
|
+
"evolution",
|
|
956
|
+
"worldviews",
|
|
957
|
+
"consciousness"
|
|
958
|
+
],
|
|
959
|
+
"worldview": "Human consciousness evolves through a spiral of value systems (vMemes), each responding to life conditions. No stage is 'better' — but understanding the spiral explains almost everything about cultural conflict.",
|
|
960
|
+
"emotionalTone": [
|
|
961
|
+
"mind-expanding",
|
|
962
|
+
"systematic",
|
|
963
|
+
"complex",
|
|
964
|
+
"revelatory"
|
|
965
|
+
],
|
|
966
|
+
"difficulty": "challenging",
|
|
967
|
+
"pageCount": 352,
|
|
968
|
+
"bestFor": [
|
|
969
|
+
"Understanding cultural and political conflict at a deep level",
|
|
970
|
+
"Developmental psychology frameworks",
|
|
971
|
+
"Leaders managing diverse teams/societies",
|
|
972
|
+
"After reading The Righteous Mind"
|
|
973
|
+
],
|
|
974
|
+
"notFor": [
|
|
975
|
+
"Wanting simple answers",
|
|
976
|
+
"Skeptical of stage-based developmental models"
|
|
977
|
+
],
|
|
978
|
+
"connections": [
|
|
979
|
+
"the-righteous-mind",
|
|
980
|
+
"sapiens",
|
|
981
|
+
"the-true-believer"
|
|
982
|
+
],
|
|
983
|
+
"keyInsight": "People don't just disagree — they literally operate from different value systems that see the world in fundamentally incompatible ways.",
|
|
984
|
+
"bjornSays": "The most underrated book on this list. Once you see the spiral, you can't unsee it. Explains cultural clashes better than anything else I've found.",
|
|
985
|
+
"tags": [
|
|
986
|
+
"psychology",
|
|
987
|
+
"philosophy",
|
|
988
|
+
"culture",
|
|
989
|
+
"developmental"
|
|
990
|
+
],
|
|
991
|
+
"asin": "1405133562",
|
|
992
|
+
"amazonUrl": "https://www.amazon.com/dp/1405133562?tag=poorbjorn-20"
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
"id": "atlas-shrugged",
|
|
996
|
+
"title": "Atlas Shrugged",
|
|
997
|
+
"author": "Ayn Rand",
|
|
998
|
+
"year": 1957,
|
|
999
|
+
"rating": 5,
|
|
1000
|
+
"themes": [
|
|
1001
|
+
"individualism",
|
|
1002
|
+
"capitalism",
|
|
1003
|
+
"objectivism",
|
|
1004
|
+
"freedom",
|
|
1005
|
+
"production",
|
|
1006
|
+
"philosophy"
|
|
1007
|
+
],
|
|
1008
|
+
"worldview": "The individual mind is the engine of civilization. When the productive are punished and the mediocre rewarded, society collapses.",
|
|
1009
|
+
"emotionalTone": [
|
|
1010
|
+
"epic",
|
|
1011
|
+
"polarizing",
|
|
1012
|
+
"intense",
|
|
1013
|
+
"philosophical"
|
|
1014
|
+
],
|
|
1015
|
+
"difficulty": "challenging",
|
|
1016
|
+
"pageCount": 1168,
|
|
1017
|
+
"bestFor": [
|
|
1018
|
+
"Philosophy of individualism and capitalism",
|
|
1019
|
+
"Epic, idea-driven fiction",
|
|
1020
|
+
"Entrepreneurs and builders",
|
|
1021
|
+
"Understanding libertarian thought"
|
|
1022
|
+
],
|
|
1023
|
+
"notFor": [
|
|
1024
|
+
"Wanting subtle, literary fiction",
|
|
1025
|
+
"Turned off by strong ideological viewpoints",
|
|
1026
|
+
"Short attention spans"
|
|
1027
|
+
],
|
|
1028
|
+
"connections": [
|
|
1029
|
+
"the-almanack-of-naval",
|
|
1030
|
+
"the-beginning-of-infinity"
|
|
1031
|
+
],
|
|
1032
|
+
"keyInsight": "The question isn't who is going to let me; it's who is going to stop me.",
|
|
1033
|
+
"bjornSays": "Polarizing as hell, but undeniably powerful. Rand's vision of the individual against the collective stays with you whether you agree or not.",
|
|
1034
|
+
"tags": [
|
|
1035
|
+
"fiction",
|
|
1036
|
+
"philosophy",
|
|
1037
|
+
"capitalism",
|
|
1038
|
+
"epic"
|
|
1039
|
+
],
|
|
1040
|
+
"asin": "0451191145",
|
|
1041
|
+
"amazonUrl": "https://www.amazon.com/dp/0451191145?tag=poorbjorn-20"
|
|
1042
|
+
}
|
|
1043
|
+
]
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "booklab-mcp",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "BookLab by Bjorn — MCP server for nonfiction book recommendations. 10+ years of human-curated reviews, structured for AI agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "server.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"booklab-mcp": "server.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"server.js",
|
|
12
|
+
"data/book-profiles.json",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"start": "node server.js"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"books",
|
|
22
|
+
"nonfiction",
|
|
23
|
+
"recommendations",
|
|
24
|
+
"ai-agents",
|
|
25
|
+
"booklab",
|
|
26
|
+
"claude"
|
|
27
|
+
],
|
|
28
|
+
"author": "Björn Röjgren <poorbjorn@gmail.com> (https://booklabbybjorn.com)",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/poorbjorn-creator/booklab-mcp"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://booklabai.pages.dev",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.12.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/server.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { readFileSync } from "fs";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const books = JSON.parse(readFileSync(join(__dirname, "data/book-profiles.json"), "utf-8"));
|
|
11
|
+
|
|
12
|
+
// --- Semantic search engine (TF-IDF inspired, zero dependencies) ---
|
|
13
|
+
|
|
14
|
+
// Build searchable text corpus per book
|
|
15
|
+
function buildCorpus(book) {
|
|
16
|
+
return [
|
|
17
|
+
book.title,
|
|
18
|
+
book.author,
|
|
19
|
+
...book.themes,
|
|
20
|
+
...book.tags,
|
|
21
|
+
...book.bestFor,
|
|
22
|
+
...(book.notFor || []),
|
|
23
|
+
book.keyInsight,
|
|
24
|
+
book.bjornSays,
|
|
25
|
+
book.worldview || "",
|
|
26
|
+
book.emotionalTone || "",
|
|
27
|
+
...(book.connections || []).map(c => `${c.book} ${c.relationship}`),
|
|
28
|
+
].join(" ").toLowerCase();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Tokenize: split, remove short/stop words
|
|
32
|
+
const STOP = new Set(["the","a","an","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","shall","can","to","of","in","for","on","with","at","by","from","as","into","through","during","before","after","above","below","between","but","and","or","nor","not","so","yet","both","either","neither","each","every","all","any","few","more","most","other","some","such","no","only","own","same","than","too","very","just","about","it","its","this","that","these","those","i","me","my","we","our","you","your","he","him","his","she","her","they","them","their","what","which","who","whom","how","when","where","why"]);
|
|
33
|
+
|
|
34
|
+
function tokenize(text) {
|
|
35
|
+
return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter(w => w.length > 2 && !STOP.has(w));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Synonym/concept expansion for common queries
|
|
39
|
+
const CONCEPT_MAP = {
|
|
40
|
+
meaning: ["purpose", "existential", "fulfillment", "meaning", "why"],
|
|
41
|
+
depression: ["sadness", "loss", "grief", "disconnection", "mental", "despair"],
|
|
42
|
+
anxiety: ["fear", "stress", "worry", "uncertainty", "overwhelm"],
|
|
43
|
+
leadership: ["influence", "power", "authority", "management", "leading"],
|
|
44
|
+
happiness: ["joy", "wellbeing", "fulfillment", "flourishing", "flow", "satisfaction"],
|
|
45
|
+
relationships: ["love", "connection", "empathy", "social", "belonging"],
|
|
46
|
+
productivity: ["focus", "discipline", "habits", "work", "deep", "efficiency"],
|
|
47
|
+
philosophy: ["existentialism", "stoicism", "ethics", "morality", "wisdom", "philosophical"],
|
|
48
|
+
psychology: ["mind", "behavior", "cognitive", "emotional", "mental", "psychological"],
|
|
49
|
+
history: ["civilization", "historical", "war", "society", "humanity", "evolution"],
|
|
50
|
+
death: ["mortality", "dying", "death", "grief", "loss", "finite"],
|
|
51
|
+
freedom: ["liberty", "autonomy", "independence", "individualism", "free"],
|
|
52
|
+
society: ["civilization", "culture", "collective", "social", "political", "community"],
|
|
53
|
+
money: ["economics", "wealth", "financial", "capitalism", "bitcoin"],
|
|
54
|
+
technology: ["tech", "digital", "ai", "innovation", "disruption", "future"],
|
|
55
|
+
suffering: ["pain", "trauma", "adversity", "hardship", "struggle", "resilience"],
|
|
56
|
+
identity: ["self", "ego", "personality", "individuality", "authenticity"],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
function expandQuery(tokens) {
|
|
60
|
+
const expanded = new Set(tokens);
|
|
61
|
+
for (const token of tokens) {
|
|
62
|
+
for (const [concept, synonyms] of Object.entries(CONCEPT_MAP)) {
|
|
63
|
+
if (token === concept || synonyms.includes(token)) {
|
|
64
|
+
expanded.add(concept);
|
|
65
|
+
for (const s of synonyms) expanded.add(s);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return [...expanded];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Build IDF from corpus
|
|
73
|
+
const corpusTexts = books.map(buildCorpus);
|
|
74
|
+
const corpusTokens = corpusTexts.map(tokenize);
|
|
75
|
+
const docCount = books.length;
|
|
76
|
+
const df = {};
|
|
77
|
+
for (const tokens of corpusTokens) {
|
|
78
|
+
const unique = new Set(tokens);
|
|
79
|
+
for (const t of unique) df[t] = (df[t] || 0) + 1;
|
|
80
|
+
}
|
|
81
|
+
function idf(term) {
|
|
82
|
+
return Math.log((docCount + 1) / ((df[term] || 0) + 1)) + 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Score a query against a book
|
|
86
|
+
function scoreBook(queryTokens, bookIndex) {
|
|
87
|
+
const bookTokenSet = corpusTokens[bookIndex];
|
|
88
|
+
const bookTf = {};
|
|
89
|
+
for (const t of bookTokenSet) bookTf[t] = (bookTf[t] || 0) + 1;
|
|
90
|
+
const maxTf = Math.max(...Object.values(bookTf), 1);
|
|
91
|
+
|
|
92
|
+
let score = 0;
|
|
93
|
+
for (const qt of queryTokens) {
|
|
94
|
+
if (bookTf[qt]) {
|
|
95
|
+
const tf = 0.5 + 0.5 * (bookTf[qt] / maxTf);
|
|
96
|
+
score += tf * idf(qt);
|
|
97
|
+
}
|
|
98
|
+
// Partial match bonus (prefix)
|
|
99
|
+
for (const bt of Object.keys(bookTf)) {
|
|
100
|
+
if (bt !== qt && (bt.startsWith(qt) || qt.startsWith(bt)) && Math.abs(bt.length - qt.length) <= 3) {
|
|
101
|
+
score += 0.3 * idf(bt);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Boost 5-star books
|
|
106
|
+
if (books[bookIndex].rating === 5) score *= 1.1;
|
|
107
|
+
return score;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function searchBooks(query, topN = 5) {
|
|
111
|
+
const tokens = tokenize(query);
|
|
112
|
+
const expanded = expandQuery(tokens);
|
|
113
|
+
const results = books.map((book, i) => ({ ...book, score: scoreBook(expanded, i) }));
|
|
114
|
+
return results.filter(b => b.score > 0).sort((a, b) => b.score - a.score).slice(0, topN);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// --- MCP Server ---
|
|
118
|
+
|
|
119
|
+
const server = new McpServer({
|
|
120
|
+
name: "booklab",
|
|
121
|
+
version: "0.4.0",
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Tool: recommend books based on a situation or question
|
|
125
|
+
server.tool(
|
|
126
|
+
"recommend",
|
|
127
|
+
"Get nonfiction book recommendations from BookLab's curated library. Describe a situation, question, or topic — get ranked recommendations with reasoning.",
|
|
128
|
+
{ query: z.string().describe("What the reader needs — a problem, question, topic, or mood"), count: z.number().optional().describe("Number of recommendations (default 3, max 5)") },
|
|
129
|
+
async ({ query, count }) => {
|
|
130
|
+
const n = Math.min(count || 3, 5);
|
|
131
|
+
const results = searchBooks(query, n);
|
|
132
|
+
|
|
133
|
+
if (results.length === 0) {
|
|
134
|
+
return {
|
|
135
|
+
content: [{ type: "text", text: `No strong matches in BookLab's library for "${query}". Try describing what you're going through or what you want to learn. Library has ${books.length} curated nonfiction titles.` }],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const text = results
|
|
140
|
+
.map((b, i) => `${i + 1}. **${b.title}** by ${b.author} (${b.rating}/5)\n _${b.bjornSays}_\n Key insight: ${b.keyInsight}\n Themes: ${b.themes.join(", ")}\n Best for: ${b.bestFor.join(", ")}${b.amazonUrl ? `\n 📚 Get it: ${b.amazonUrl}` : ""}`)
|
|
141
|
+
.join("\n\n");
|
|
142
|
+
|
|
143
|
+
return { content: [{ type: "text", text: `BookLab recommends (from ${books.length} curated nonfiction books):\n\n${text}` }] };
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
// Tool: get detailed profile of a specific book
|
|
148
|
+
server.tool(
|
|
149
|
+
"book_profile",
|
|
150
|
+
"Get the full structured profile of a specific book from BookLab's library.",
|
|
151
|
+
{ title: z.string().describe("Book title (partial match OK)") },
|
|
152
|
+
async ({ title }) => {
|
|
153
|
+
const t = title.toLowerCase();
|
|
154
|
+
const book = books.find((b) => b.title.toLowerCase().includes(t) || b.id.includes(t.replace(/\s+/g, "-")));
|
|
155
|
+
if (!book) {
|
|
156
|
+
return { content: [{ type: "text", text: `Book not found: "${title}". Available: ${books.map((b) => b.title).join(", ")}` }] };
|
|
157
|
+
}
|
|
158
|
+
return { content: [{ type: "text", text: JSON.stringify(book, null, 2) }] };
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Tool: list all books
|
|
163
|
+
server.tool(
|
|
164
|
+
"list_books",
|
|
165
|
+
"List all books in BookLab's curated nonfiction library.",
|
|
166
|
+
{},
|
|
167
|
+
async () => {
|
|
168
|
+
const text = books
|
|
169
|
+
.map((b) => `• ${b.title} — ${b.author} (${b.rating}/5) [${b.tags.join(", ")}]`)
|
|
170
|
+
.join("\n");
|
|
171
|
+
return { content: [{ type: "text", text: `BookLab Library (${books.length} books):\n\n${text}` }] };
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
// Tool: explore themes and topics in the library
|
|
176
|
+
server.tool(
|
|
177
|
+
"explore_themes",
|
|
178
|
+
"Discover what themes and topics BookLab's library covers. Returns all unique themes with book counts, or filter by a topic to see related themes.",
|
|
179
|
+
{ topic: z.string().optional().describe("Optional topic to filter themes by (e.g. 'psychology', 'freedom')") },
|
|
180
|
+
async ({ topic }) => {
|
|
181
|
+
const themeMap = {};
|
|
182
|
+
for (const book of books) {
|
|
183
|
+
for (const theme of book.themes) {
|
|
184
|
+
if (!themeMap[theme]) themeMap[theme] = [];
|
|
185
|
+
themeMap[theme].push(book.title);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
let entries = Object.entries(themeMap);
|
|
189
|
+
if (topic) {
|
|
190
|
+
const t = topic.toLowerCase();
|
|
191
|
+
entries = entries.filter(([theme]) => theme.toLowerCase().includes(t));
|
|
192
|
+
if (entries.length === 0) {
|
|
193
|
+
return { content: [{ type: "text", text: `No themes matching "${topic}". Try: ${Object.keys(themeMap).slice(0, 15).join(", ")}...` }] };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
entries.sort((a, b) => b[1].length - a[1].length);
|
|
197
|
+
const text = entries.map(([theme, titles]) => `• **${theme}** (${titles.length}): ${titles.join(", ")}`).join("\n");
|
|
198
|
+
return { content: [{ type: "text", text: `BookLab Themes${topic ? ` matching "${topic}"` : ""}:\n\n${text}` }] };
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// Tool: find connections between books
|
|
203
|
+
server.tool(
|
|
204
|
+
"book_connections",
|
|
205
|
+
"Find how books in BookLab's library connect to each other. Shows intellectual relationships and reading paths.",
|
|
206
|
+
{ title: z.string().describe("Book title to find connections for (partial match OK)") },
|
|
207
|
+
async ({ title }) => {
|
|
208
|
+
const t = title.toLowerCase();
|
|
209
|
+
const book = books.find((b) => b.title.toLowerCase().includes(t) || b.id.includes(t.replace(/\s+/g, "-")));
|
|
210
|
+
if (!book) {
|
|
211
|
+
return { content: [{ type: "text", text: `Book not found: "${title}". Available: ${books.map((b) => b.title).join(", ")}` }] };
|
|
212
|
+
}
|
|
213
|
+
if (!book.connections || book.connections.length === 0) {
|
|
214
|
+
return { content: [{ type: "text", text: `No mapped connections for "${book.title}" yet. Try recommend tool to find thematically similar books.` }] };
|
|
215
|
+
}
|
|
216
|
+
const text = book.connections.map(c => `• **${c.book}** — ${c.relationship}`).join("\n");
|
|
217
|
+
return { content: [{ type: "text", text: `Connections from **${book.title}** by ${book.author}:\n\n${text}` }] };
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
// Resource: expose the full library as a resource
|
|
222
|
+
server.resource("library", "booklab://library", async (uri) => ({
|
|
223
|
+
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(books, null, 2) }],
|
|
224
|
+
}));
|
|
225
|
+
|
|
226
|
+
const transport = new StdioServerTransport();
|
|
227
|
+
await server.connect(transport);
|