@iflow-mcp/kdcokenny-lsbible 0.3.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 +529 -0
- package/dist/index.cjs +2269 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +81 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +2254 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.cjs +2716 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +230 -0
- package/dist/mcp/index.d.ts +230 -0
- package/dist/mcp/index.js +2707 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/stdio.cjs +2709 -0
- package/dist/mcp/stdio.cjs.map +1 -0
- package/dist/mcp/stdio.d.cts +1 -0
- package/dist/mcp/stdio.d.ts +1 -0
- package/dist/mcp/stdio.js +2707 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/noop-B62cxzKZ.d.cts +1157 -0
- package/dist/noop-B62cxzKZ.d.ts +1157 -0
- package/package.json +1 -0
|
@@ -0,0 +1,2716 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
4
|
+
var zod = require('zod');
|
|
5
|
+
var linkedom = require('linkedom');
|
|
6
|
+
|
|
7
|
+
// src/mcp/server.ts
|
|
8
|
+
function registerPrompts(server) {
|
|
9
|
+
server.registerPrompt(
|
|
10
|
+
"bible_study",
|
|
11
|
+
{
|
|
12
|
+
title: "Bible Study Guide",
|
|
13
|
+
description: "Generate a comprehensive Bible study guide for a passage",
|
|
14
|
+
argsSchema: {
|
|
15
|
+
passage: zod.z.string().describe('Bible passage reference (e.g., "John 3:16-21")'),
|
|
16
|
+
focusAreas: zod.z.string().optional().describe(
|
|
17
|
+
'Optional comma-separated areas to focus on (e.g., "context, application, cross-references")'
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
(args) => {
|
|
22
|
+
const { passage, focusAreas } = args;
|
|
23
|
+
const focusText = focusAreas ? `
|
|
24
|
+
|
|
25
|
+
Focus areas: ${focusAreas}` : "";
|
|
26
|
+
return {
|
|
27
|
+
messages: [
|
|
28
|
+
{
|
|
29
|
+
role: "user",
|
|
30
|
+
content: {
|
|
31
|
+
type: "text",
|
|
32
|
+
text: `Create a comprehensive Bible study guide for ${passage}.
|
|
33
|
+
|
|
34
|
+
Include:
|
|
35
|
+
1. Historical and cultural context
|
|
36
|
+
2. Key themes and theological insights
|
|
37
|
+
3. Practical applications for modern readers
|
|
38
|
+
4. Discussion questions
|
|
39
|
+
5. Cross-references to related passages${focusText}`
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
server.registerPrompt(
|
|
47
|
+
"cross_reference",
|
|
48
|
+
{
|
|
49
|
+
title: "Find Cross References",
|
|
50
|
+
description: "Find verses related to a specific verse",
|
|
51
|
+
argsSchema: {
|
|
52
|
+
verse: zod.z.string().describe('Bible verse reference (e.g., "Romans 8:28")'),
|
|
53
|
+
maxResults: zod.z.string().optional().describe("Maximum number of results (default: 10)")
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
(args) => {
|
|
57
|
+
const { verse, maxResults: maxResultsStr } = args;
|
|
58
|
+
const maxResults = maxResultsStr ? Number.parseInt(maxResultsStr, 10) : 10;
|
|
59
|
+
return {
|
|
60
|
+
messages: [
|
|
61
|
+
{
|
|
62
|
+
role: "user",
|
|
63
|
+
content: {
|
|
64
|
+
type: "text",
|
|
65
|
+
text: `Find up to ${maxResults} Bible verses that are thematically related to ${verse}.
|
|
66
|
+
|
|
67
|
+
For each related verse:
|
|
68
|
+
1. Explain the thematic connection
|
|
69
|
+
2. Note any parallel language or concepts
|
|
70
|
+
3. Highlight complementary or contrasting perspectives`
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/books.ts
|
|
80
|
+
var BIBLE_STRUCTURE = {
|
|
81
|
+
1: {
|
|
82
|
+
number: 1,
|
|
83
|
+
name: "Genesis",
|
|
84
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
85
|
+
chapters: 50,
|
|
86
|
+
verses: [
|
|
87
|
+
31,
|
|
88
|
+
25,
|
|
89
|
+
24,
|
|
90
|
+
26,
|
|
91
|
+
32,
|
|
92
|
+
22,
|
|
93
|
+
24,
|
|
94
|
+
22,
|
|
95
|
+
29,
|
|
96
|
+
32,
|
|
97
|
+
32,
|
|
98
|
+
20,
|
|
99
|
+
18,
|
|
100
|
+
24,
|
|
101
|
+
21,
|
|
102
|
+
16,
|
|
103
|
+
27,
|
|
104
|
+
33,
|
|
105
|
+
38,
|
|
106
|
+
18,
|
|
107
|
+
34,
|
|
108
|
+
24,
|
|
109
|
+
20,
|
|
110
|
+
67,
|
|
111
|
+
34,
|
|
112
|
+
35,
|
|
113
|
+
46,
|
|
114
|
+
22,
|
|
115
|
+
35,
|
|
116
|
+
43,
|
|
117
|
+
55,
|
|
118
|
+
32,
|
|
119
|
+
20,
|
|
120
|
+
31,
|
|
121
|
+
29,
|
|
122
|
+
43,
|
|
123
|
+
36,
|
|
124
|
+
30,
|
|
125
|
+
23,
|
|
126
|
+
23,
|
|
127
|
+
57,
|
|
128
|
+
38,
|
|
129
|
+
34,
|
|
130
|
+
34,
|
|
131
|
+
28,
|
|
132
|
+
34,
|
|
133
|
+
31,
|
|
134
|
+
22,
|
|
135
|
+
33,
|
|
136
|
+
26
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
2: {
|
|
140
|
+
number: 2,
|
|
141
|
+
name: "Exodus",
|
|
142
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
143
|
+
chapters: 40,
|
|
144
|
+
verses: [
|
|
145
|
+
22,
|
|
146
|
+
25,
|
|
147
|
+
22,
|
|
148
|
+
31,
|
|
149
|
+
23,
|
|
150
|
+
30,
|
|
151
|
+
25,
|
|
152
|
+
32,
|
|
153
|
+
35,
|
|
154
|
+
29,
|
|
155
|
+
10,
|
|
156
|
+
51,
|
|
157
|
+
22,
|
|
158
|
+
31,
|
|
159
|
+
27,
|
|
160
|
+
36,
|
|
161
|
+
16,
|
|
162
|
+
27,
|
|
163
|
+
25,
|
|
164
|
+
26,
|
|
165
|
+
36,
|
|
166
|
+
31,
|
|
167
|
+
33,
|
|
168
|
+
18,
|
|
169
|
+
40,
|
|
170
|
+
37,
|
|
171
|
+
21,
|
|
172
|
+
43,
|
|
173
|
+
46,
|
|
174
|
+
38,
|
|
175
|
+
18,
|
|
176
|
+
35,
|
|
177
|
+
23,
|
|
178
|
+
35,
|
|
179
|
+
35,
|
|
180
|
+
38,
|
|
181
|
+
29,
|
|
182
|
+
31,
|
|
183
|
+
43,
|
|
184
|
+
38
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
3: {
|
|
188
|
+
number: 3,
|
|
189
|
+
name: "Leviticus",
|
|
190
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
191
|
+
chapters: 27,
|
|
192
|
+
verses: [
|
|
193
|
+
17,
|
|
194
|
+
16,
|
|
195
|
+
17,
|
|
196
|
+
35,
|
|
197
|
+
19,
|
|
198
|
+
30,
|
|
199
|
+
38,
|
|
200
|
+
36,
|
|
201
|
+
24,
|
|
202
|
+
20,
|
|
203
|
+
47,
|
|
204
|
+
8,
|
|
205
|
+
59,
|
|
206
|
+
57,
|
|
207
|
+
33,
|
|
208
|
+
34,
|
|
209
|
+
16,
|
|
210
|
+
30,
|
|
211
|
+
37,
|
|
212
|
+
27,
|
|
213
|
+
24,
|
|
214
|
+
33,
|
|
215
|
+
44,
|
|
216
|
+
23,
|
|
217
|
+
55,
|
|
218
|
+
46,
|
|
219
|
+
34
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
4: {
|
|
223
|
+
number: 4,
|
|
224
|
+
name: "Numbers",
|
|
225
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
226
|
+
chapters: 36,
|
|
227
|
+
verses: [
|
|
228
|
+
54,
|
|
229
|
+
34,
|
|
230
|
+
51,
|
|
231
|
+
49,
|
|
232
|
+
31,
|
|
233
|
+
27,
|
|
234
|
+
89,
|
|
235
|
+
26,
|
|
236
|
+
23,
|
|
237
|
+
36,
|
|
238
|
+
35,
|
|
239
|
+
16,
|
|
240
|
+
33,
|
|
241
|
+
45,
|
|
242
|
+
41,
|
|
243
|
+
50,
|
|
244
|
+
13,
|
|
245
|
+
32,
|
|
246
|
+
22,
|
|
247
|
+
29,
|
|
248
|
+
35,
|
|
249
|
+
41,
|
|
250
|
+
30,
|
|
251
|
+
25,
|
|
252
|
+
18,
|
|
253
|
+
65,
|
|
254
|
+
23,
|
|
255
|
+
31,
|
|
256
|
+
40,
|
|
257
|
+
16,
|
|
258
|
+
54,
|
|
259
|
+
42,
|
|
260
|
+
56,
|
|
261
|
+
29,
|
|
262
|
+
34,
|
|
263
|
+
13
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
5: {
|
|
267
|
+
number: 5,
|
|
268
|
+
name: "Deuteronomy",
|
|
269
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
270
|
+
chapters: 34,
|
|
271
|
+
verses: [
|
|
272
|
+
46,
|
|
273
|
+
37,
|
|
274
|
+
29,
|
|
275
|
+
49,
|
|
276
|
+
33,
|
|
277
|
+
25,
|
|
278
|
+
26,
|
|
279
|
+
20,
|
|
280
|
+
29,
|
|
281
|
+
22,
|
|
282
|
+
32,
|
|
283
|
+
32,
|
|
284
|
+
18,
|
|
285
|
+
29,
|
|
286
|
+
23,
|
|
287
|
+
22,
|
|
288
|
+
20,
|
|
289
|
+
22,
|
|
290
|
+
21,
|
|
291
|
+
20,
|
|
292
|
+
23,
|
|
293
|
+
30,
|
|
294
|
+
25,
|
|
295
|
+
22,
|
|
296
|
+
19,
|
|
297
|
+
19,
|
|
298
|
+
26,
|
|
299
|
+
68,
|
|
300
|
+
29,
|
|
301
|
+
20,
|
|
302
|
+
30,
|
|
303
|
+
52,
|
|
304
|
+
29,
|
|
305
|
+
12
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
6: {
|
|
309
|
+
number: 6,
|
|
310
|
+
name: "Joshua",
|
|
311
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
312
|
+
chapters: 24,
|
|
313
|
+
verses: [
|
|
314
|
+
18,
|
|
315
|
+
24,
|
|
316
|
+
17,
|
|
317
|
+
24,
|
|
318
|
+
15,
|
|
319
|
+
27,
|
|
320
|
+
26,
|
|
321
|
+
35,
|
|
322
|
+
27,
|
|
323
|
+
43,
|
|
324
|
+
23,
|
|
325
|
+
24,
|
|
326
|
+
33,
|
|
327
|
+
15,
|
|
328
|
+
63,
|
|
329
|
+
10,
|
|
330
|
+
18,
|
|
331
|
+
28,
|
|
332
|
+
51,
|
|
333
|
+
9,
|
|
334
|
+
45,
|
|
335
|
+
34,
|
|
336
|
+
16,
|
|
337
|
+
33
|
|
338
|
+
]
|
|
339
|
+
},
|
|
340
|
+
7: {
|
|
341
|
+
number: 7,
|
|
342
|
+
name: "Judges",
|
|
343
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
344
|
+
chapters: 21,
|
|
345
|
+
verses: [36, 23, 31, 24, 31, 40, 25, 35, 57, 18, 40, 15, 25, 20, 20, 31, 13, 31, 30, 48, 25]
|
|
346
|
+
},
|
|
347
|
+
8: {
|
|
348
|
+
number: 8,
|
|
349
|
+
name: "Ruth",
|
|
350
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
351
|
+
chapters: 4,
|
|
352
|
+
verses: [22, 23, 18, 22]
|
|
353
|
+
},
|
|
354
|
+
9: {
|
|
355
|
+
number: 9,
|
|
356
|
+
name: "1 Samuel",
|
|
357
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
358
|
+
chapters: 31,
|
|
359
|
+
verses: [
|
|
360
|
+
28,
|
|
361
|
+
36,
|
|
362
|
+
21,
|
|
363
|
+
22,
|
|
364
|
+
12,
|
|
365
|
+
21,
|
|
366
|
+
17,
|
|
367
|
+
22,
|
|
368
|
+
27,
|
|
369
|
+
27,
|
|
370
|
+
15,
|
|
371
|
+
25,
|
|
372
|
+
23,
|
|
373
|
+
52,
|
|
374
|
+
35,
|
|
375
|
+
23,
|
|
376
|
+
58,
|
|
377
|
+
30,
|
|
378
|
+
24,
|
|
379
|
+
42,
|
|
380
|
+
15,
|
|
381
|
+
23,
|
|
382
|
+
29,
|
|
383
|
+
22,
|
|
384
|
+
44,
|
|
385
|
+
25,
|
|
386
|
+
12,
|
|
387
|
+
25,
|
|
388
|
+
11,
|
|
389
|
+
31,
|
|
390
|
+
13
|
|
391
|
+
]
|
|
392
|
+
},
|
|
393
|
+
10: {
|
|
394
|
+
number: 10,
|
|
395
|
+
name: "2 Samuel",
|
|
396
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
397
|
+
chapters: 24,
|
|
398
|
+
verses: [
|
|
399
|
+
27,
|
|
400
|
+
32,
|
|
401
|
+
39,
|
|
402
|
+
12,
|
|
403
|
+
25,
|
|
404
|
+
23,
|
|
405
|
+
29,
|
|
406
|
+
18,
|
|
407
|
+
13,
|
|
408
|
+
19,
|
|
409
|
+
27,
|
|
410
|
+
31,
|
|
411
|
+
39,
|
|
412
|
+
33,
|
|
413
|
+
37,
|
|
414
|
+
23,
|
|
415
|
+
29,
|
|
416
|
+
33,
|
|
417
|
+
43,
|
|
418
|
+
26,
|
|
419
|
+
22,
|
|
420
|
+
51,
|
|
421
|
+
39,
|
|
422
|
+
25
|
|
423
|
+
]
|
|
424
|
+
},
|
|
425
|
+
11: {
|
|
426
|
+
number: 11,
|
|
427
|
+
name: "1 Kings",
|
|
428
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
429
|
+
chapters: 22,
|
|
430
|
+
verses: [
|
|
431
|
+
53,
|
|
432
|
+
46,
|
|
433
|
+
28,
|
|
434
|
+
34,
|
|
435
|
+
18,
|
|
436
|
+
38,
|
|
437
|
+
51,
|
|
438
|
+
66,
|
|
439
|
+
28,
|
|
440
|
+
29,
|
|
441
|
+
43,
|
|
442
|
+
33,
|
|
443
|
+
34,
|
|
444
|
+
31,
|
|
445
|
+
34,
|
|
446
|
+
34,
|
|
447
|
+
24,
|
|
448
|
+
46,
|
|
449
|
+
21,
|
|
450
|
+
43,
|
|
451
|
+
29,
|
|
452
|
+
53
|
|
453
|
+
]
|
|
454
|
+
},
|
|
455
|
+
12: {
|
|
456
|
+
number: 12,
|
|
457
|
+
name: "2 Kings",
|
|
458
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
459
|
+
chapters: 25,
|
|
460
|
+
verses: [
|
|
461
|
+
18,
|
|
462
|
+
25,
|
|
463
|
+
27,
|
|
464
|
+
44,
|
|
465
|
+
27,
|
|
466
|
+
33,
|
|
467
|
+
20,
|
|
468
|
+
29,
|
|
469
|
+
37,
|
|
470
|
+
36,
|
|
471
|
+
21,
|
|
472
|
+
21,
|
|
473
|
+
25,
|
|
474
|
+
29,
|
|
475
|
+
38,
|
|
476
|
+
20,
|
|
477
|
+
41,
|
|
478
|
+
37,
|
|
479
|
+
37,
|
|
480
|
+
21,
|
|
481
|
+
26,
|
|
482
|
+
20,
|
|
483
|
+
37,
|
|
484
|
+
20,
|
|
485
|
+
30
|
|
486
|
+
]
|
|
487
|
+
},
|
|
488
|
+
13: {
|
|
489
|
+
number: 13,
|
|
490
|
+
name: "1 Chronicles",
|
|
491
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
492
|
+
chapters: 29,
|
|
493
|
+
verses: [
|
|
494
|
+
54,
|
|
495
|
+
55,
|
|
496
|
+
24,
|
|
497
|
+
43,
|
|
498
|
+
26,
|
|
499
|
+
81,
|
|
500
|
+
40,
|
|
501
|
+
40,
|
|
502
|
+
44,
|
|
503
|
+
14,
|
|
504
|
+
47,
|
|
505
|
+
40,
|
|
506
|
+
14,
|
|
507
|
+
17,
|
|
508
|
+
29,
|
|
509
|
+
43,
|
|
510
|
+
27,
|
|
511
|
+
17,
|
|
512
|
+
19,
|
|
513
|
+
8,
|
|
514
|
+
30,
|
|
515
|
+
19,
|
|
516
|
+
32,
|
|
517
|
+
31,
|
|
518
|
+
31,
|
|
519
|
+
32,
|
|
520
|
+
34,
|
|
521
|
+
21,
|
|
522
|
+
30
|
|
523
|
+
]
|
|
524
|
+
},
|
|
525
|
+
14: {
|
|
526
|
+
number: 14,
|
|
527
|
+
name: "2 Chronicles",
|
|
528
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
529
|
+
chapters: 36,
|
|
530
|
+
verses: [
|
|
531
|
+
17,
|
|
532
|
+
18,
|
|
533
|
+
17,
|
|
534
|
+
22,
|
|
535
|
+
14,
|
|
536
|
+
42,
|
|
537
|
+
22,
|
|
538
|
+
18,
|
|
539
|
+
31,
|
|
540
|
+
19,
|
|
541
|
+
23,
|
|
542
|
+
16,
|
|
543
|
+
22,
|
|
544
|
+
15,
|
|
545
|
+
19,
|
|
546
|
+
14,
|
|
547
|
+
19,
|
|
548
|
+
34,
|
|
549
|
+
11,
|
|
550
|
+
37,
|
|
551
|
+
20,
|
|
552
|
+
12,
|
|
553
|
+
21,
|
|
554
|
+
27,
|
|
555
|
+
28,
|
|
556
|
+
23,
|
|
557
|
+
9,
|
|
558
|
+
27,
|
|
559
|
+
36,
|
|
560
|
+
27,
|
|
561
|
+
21,
|
|
562
|
+
33,
|
|
563
|
+
25,
|
|
564
|
+
33,
|
|
565
|
+
27,
|
|
566
|
+
23
|
|
567
|
+
]
|
|
568
|
+
},
|
|
569
|
+
15: {
|
|
570
|
+
number: 15,
|
|
571
|
+
name: "Ezra",
|
|
572
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
573
|
+
chapters: 10,
|
|
574
|
+
verses: [11, 70, 13, 24, 17, 22, 28, 36, 15, 44]
|
|
575
|
+
},
|
|
576
|
+
16: {
|
|
577
|
+
number: 16,
|
|
578
|
+
name: "Nehemiah",
|
|
579
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
580
|
+
chapters: 13,
|
|
581
|
+
verses: [11, 20, 32, 23, 19, 19, 73, 18, 38, 39, 36, 47, 31]
|
|
582
|
+
},
|
|
583
|
+
17: {
|
|
584
|
+
number: 17,
|
|
585
|
+
name: "Esther",
|
|
586
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
587
|
+
chapters: 10,
|
|
588
|
+
verses: [22, 23, 15, 17, 14, 14, 10, 17, 32, 3]
|
|
589
|
+
},
|
|
590
|
+
18: {
|
|
591
|
+
number: 18,
|
|
592
|
+
name: "Job",
|
|
593
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
594
|
+
chapters: 42,
|
|
595
|
+
verses: [
|
|
596
|
+
22,
|
|
597
|
+
13,
|
|
598
|
+
26,
|
|
599
|
+
21,
|
|
600
|
+
27,
|
|
601
|
+
30,
|
|
602
|
+
21,
|
|
603
|
+
22,
|
|
604
|
+
35,
|
|
605
|
+
22,
|
|
606
|
+
20,
|
|
607
|
+
25,
|
|
608
|
+
28,
|
|
609
|
+
22,
|
|
610
|
+
35,
|
|
611
|
+
22,
|
|
612
|
+
16,
|
|
613
|
+
21,
|
|
614
|
+
29,
|
|
615
|
+
29,
|
|
616
|
+
34,
|
|
617
|
+
30,
|
|
618
|
+
17,
|
|
619
|
+
25,
|
|
620
|
+
6,
|
|
621
|
+
14,
|
|
622
|
+
23,
|
|
623
|
+
28,
|
|
624
|
+
25,
|
|
625
|
+
31,
|
|
626
|
+
40,
|
|
627
|
+
22,
|
|
628
|
+
33,
|
|
629
|
+
37,
|
|
630
|
+
16,
|
|
631
|
+
33,
|
|
632
|
+
24,
|
|
633
|
+
41,
|
|
634
|
+
30,
|
|
635
|
+
24,
|
|
636
|
+
34,
|
|
637
|
+
17
|
|
638
|
+
]
|
|
639
|
+
},
|
|
640
|
+
19: {
|
|
641
|
+
number: 19,
|
|
642
|
+
name: "Psalms",
|
|
643
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
644
|
+
chapters: 150,
|
|
645
|
+
verses: [
|
|
646
|
+
6,
|
|
647
|
+
12,
|
|
648
|
+
8,
|
|
649
|
+
8,
|
|
650
|
+
12,
|
|
651
|
+
10,
|
|
652
|
+
17,
|
|
653
|
+
9,
|
|
654
|
+
20,
|
|
655
|
+
18,
|
|
656
|
+
7,
|
|
657
|
+
8,
|
|
658
|
+
6,
|
|
659
|
+
7,
|
|
660
|
+
5,
|
|
661
|
+
11,
|
|
662
|
+
15,
|
|
663
|
+
50,
|
|
664
|
+
14,
|
|
665
|
+
9,
|
|
666
|
+
13,
|
|
667
|
+
31,
|
|
668
|
+
6,
|
|
669
|
+
10,
|
|
670
|
+
22,
|
|
671
|
+
12,
|
|
672
|
+
14,
|
|
673
|
+
9,
|
|
674
|
+
11,
|
|
675
|
+
12,
|
|
676
|
+
24,
|
|
677
|
+
11,
|
|
678
|
+
22,
|
|
679
|
+
22,
|
|
680
|
+
28,
|
|
681
|
+
12,
|
|
682
|
+
40,
|
|
683
|
+
22,
|
|
684
|
+
13,
|
|
685
|
+
17,
|
|
686
|
+
13,
|
|
687
|
+
11,
|
|
688
|
+
5,
|
|
689
|
+
26,
|
|
690
|
+
17,
|
|
691
|
+
11,
|
|
692
|
+
9,
|
|
693
|
+
14,
|
|
694
|
+
20,
|
|
695
|
+
23,
|
|
696
|
+
19,
|
|
697
|
+
9,
|
|
698
|
+
6,
|
|
699
|
+
7,
|
|
700
|
+
23,
|
|
701
|
+
13,
|
|
702
|
+
11,
|
|
703
|
+
11,
|
|
704
|
+
17,
|
|
705
|
+
12,
|
|
706
|
+
8,
|
|
707
|
+
12,
|
|
708
|
+
11,
|
|
709
|
+
10,
|
|
710
|
+
13,
|
|
711
|
+
20,
|
|
712
|
+
7,
|
|
713
|
+
35,
|
|
714
|
+
36,
|
|
715
|
+
5,
|
|
716
|
+
24,
|
|
717
|
+
20,
|
|
718
|
+
28,
|
|
719
|
+
23,
|
|
720
|
+
10,
|
|
721
|
+
12,
|
|
722
|
+
20,
|
|
723
|
+
72,
|
|
724
|
+
13,
|
|
725
|
+
19,
|
|
726
|
+
16,
|
|
727
|
+
8,
|
|
728
|
+
18,
|
|
729
|
+
12,
|
|
730
|
+
13,
|
|
731
|
+
17,
|
|
732
|
+
7,
|
|
733
|
+
18,
|
|
734
|
+
52,
|
|
735
|
+
17,
|
|
736
|
+
16,
|
|
737
|
+
15,
|
|
738
|
+
5,
|
|
739
|
+
23,
|
|
740
|
+
11,
|
|
741
|
+
13,
|
|
742
|
+
12,
|
|
743
|
+
9,
|
|
744
|
+
9,
|
|
745
|
+
5,
|
|
746
|
+
8,
|
|
747
|
+
28,
|
|
748
|
+
22,
|
|
749
|
+
35,
|
|
750
|
+
45,
|
|
751
|
+
48,
|
|
752
|
+
43,
|
|
753
|
+
13,
|
|
754
|
+
31,
|
|
755
|
+
7,
|
|
756
|
+
10,
|
|
757
|
+
10,
|
|
758
|
+
9,
|
|
759
|
+
8,
|
|
760
|
+
18,
|
|
761
|
+
19,
|
|
762
|
+
2,
|
|
763
|
+
29,
|
|
764
|
+
176,
|
|
765
|
+
7,
|
|
766
|
+
8,
|
|
767
|
+
9,
|
|
768
|
+
4,
|
|
769
|
+
8,
|
|
770
|
+
5,
|
|
771
|
+
6,
|
|
772
|
+
5,
|
|
773
|
+
6,
|
|
774
|
+
8,
|
|
775
|
+
8,
|
|
776
|
+
3,
|
|
777
|
+
18,
|
|
778
|
+
3,
|
|
779
|
+
3,
|
|
780
|
+
21,
|
|
781
|
+
26,
|
|
782
|
+
9,
|
|
783
|
+
8,
|
|
784
|
+
24,
|
|
785
|
+
13,
|
|
786
|
+
10,
|
|
787
|
+
7,
|
|
788
|
+
12,
|
|
789
|
+
15,
|
|
790
|
+
21,
|
|
791
|
+
10,
|
|
792
|
+
20,
|
|
793
|
+
14,
|
|
794
|
+
9,
|
|
795
|
+
6
|
|
796
|
+
]
|
|
797
|
+
},
|
|
798
|
+
20: {
|
|
799
|
+
number: 20,
|
|
800
|
+
name: "Proverbs",
|
|
801
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
802
|
+
chapters: 31,
|
|
803
|
+
verses: [
|
|
804
|
+
33,
|
|
805
|
+
22,
|
|
806
|
+
35,
|
|
807
|
+
27,
|
|
808
|
+
23,
|
|
809
|
+
35,
|
|
810
|
+
27,
|
|
811
|
+
36,
|
|
812
|
+
18,
|
|
813
|
+
32,
|
|
814
|
+
31,
|
|
815
|
+
28,
|
|
816
|
+
25,
|
|
817
|
+
35,
|
|
818
|
+
33,
|
|
819
|
+
33,
|
|
820
|
+
28,
|
|
821
|
+
24,
|
|
822
|
+
29,
|
|
823
|
+
30,
|
|
824
|
+
31,
|
|
825
|
+
29,
|
|
826
|
+
35,
|
|
827
|
+
34,
|
|
828
|
+
28,
|
|
829
|
+
28,
|
|
830
|
+
27,
|
|
831
|
+
28,
|
|
832
|
+
27,
|
|
833
|
+
33,
|
|
834
|
+
31
|
|
835
|
+
]
|
|
836
|
+
},
|
|
837
|
+
21: {
|
|
838
|
+
number: 21,
|
|
839
|
+
name: "Ecclesiastes",
|
|
840
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
841
|
+
chapters: 12,
|
|
842
|
+
verses: [18, 26, 22, 16, 20, 12, 29, 17, 18, 20, 10, 14]
|
|
843
|
+
},
|
|
844
|
+
22: {
|
|
845
|
+
number: 22,
|
|
846
|
+
name: "Song of Songs",
|
|
847
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
848
|
+
chapters: 8,
|
|
849
|
+
verses: [17, 17, 11, 16, 16, 13, 13, 14]
|
|
850
|
+
},
|
|
851
|
+
23: {
|
|
852
|
+
number: 23,
|
|
853
|
+
name: "Isaiah",
|
|
854
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
855
|
+
chapters: 66,
|
|
856
|
+
verses: [
|
|
857
|
+
31,
|
|
858
|
+
22,
|
|
859
|
+
26,
|
|
860
|
+
6,
|
|
861
|
+
30,
|
|
862
|
+
13,
|
|
863
|
+
25,
|
|
864
|
+
22,
|
|
865
|
+
21,
|
|
866
|
+
34,
|
|
867
|
+
16,
|
|
868
|
+
6,
|
|
869
|
+
22,
|
|
870
|
+
32,
|
|
871
|
+
9,
|
|
872
|
+
14,
|
|
873
|
+
14,
|
|
874
|
+
7,
|
|
875
|
+
25,
|
|
876
|
+
6,
|
|
877
|
+
17,
|
|
878
|
+
25,
|
|
879
|
+
18,
|
|
880
|
+
23,
|
|
881
|
+
12,
|
|
882
|
+
21,
|
|
883
|
+
13,
|
|
884
|
+
29,
|
|
885
|
+
24,
|
|
886
|
+
33,
|
|
887
|
+
9,
|
|
888
|
+
20,
|
|
889
|
+
24,
|
|
890
|
+
17,
|
|
891
|
+
10,
|
|
892
|
+
22,
|
|
893
|
+
38,
|
|
894
|
+
22,
|
|
895
|
+
8,
|
|
896
|
+
31,
|
|
897
|
+
29,
|
|
898
|
+
25,
|
|
899
|
+
28,
|
|
900
|
+
28,
|
|
901
|
+
25,
|
|
902
|
+
13,
|
|
903
|
+
15,
|
|
904
|
+
22,
|
|
905
|
+
26,
|
|
906
|
+
11,
|
|
907
|
+
23,
|
|
908
|
+
15,
|
|
909
|
+
12,
|
|
910
|
+
17,
|
|
911
|
+
13,
|
|
912
|
+
12,
|
|
913
|
+
21,
|
|
914
|
+
14,
|
|
915
|
+
21,
|
|
916
|
+
22,
|
|
917
|
+
11,
|
|
918
|
+
12,
|
|
919
|
+
19,
|
|
920
|
+
12,
|
|
921
|
+
25,
|
|
922
|
+
24
|
|
923
|
+
]
|
|
924
|
+
},
|
|
925
|
+
24: {
|
|
926
|
+
number: 24,
|
|
927
|
+
name: "Jeremiah",
|
|
928
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
929
|
+
chapters: 52,
|
|
930
|
+
verses: [
|
|
931
|
+
19,
|
|
932
|
+
37,
|
|
933
|
+
25,
|
|
934
|
+
31,
|
|
935
|
+
31,
|
|
936
|
+
30,
|
|
937
|
+
34,
|
|
938
|
+
22,
|
|
939
|
+
26,
|
|
940
|
+
25,
|
|
941
|
+
23,
|
|
942
|
+
17,
|
|
943
|
+
27,
|
|
944
|
+
22,
|
|
945
|
+
21,
|
|
946
|
+
21,
|
|
947
|
+
27,
|
|
948
|
+
23,
|
|
949
|
+
15,
|
|
950
|
+
18,
|
|
951
|
+
14,
|
|
952
|
+
30,
|
|
953
|
+
40,
|
|
954
|
+
10,
|
|
955
|
+
38,
|
|
956
|
+
24,
|
|
957
|
+
22,
|
|
958
|
+
17,
|
|
959
|
+
32,
|
|
960
|
+
24,
|
|
961
|
+
40,
|
|
962
|
+
44,
|
|
963
|
+
26,
|
|
964
|
+
22,
|
|
965
|
+
19,
|
|
966
|
+
32,
|
|
967
|
+
21,
|
|
968
|
+
28,
|
|
969
|
+
18,
|
|
970
|
+
16,
|
|
971
|
+
18,
|
|
972
|
+
22,
|
|
973
|
+
13,
|
|
974
|
+
30,
|
|
975
|
+
5,
|
|
976
|
+
28,
|
|
977
|
+
7,
|
|
978
|
+
47,
|
|
979
|
+
39,
|
|
980
|
+
46,
|
|
981
|
+
64,
|
|
982
|
+
34
|
|
983
|
+
]
|
|
984
|
+
},
|
|
985
|
+
25: {
|
|
986
|
+
number: 25,
|
|
987
|
+
name: "Lamentations",
|
|
988
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
989
|
+
chapters: 5,
|
|
990
|
+
verses: [22, 22, 66, 22, 22]
|
|
991
|
+
},
|
|
992
|
+
26: {
|
|
993
|
+
number: 26,
|
|
994
|
+
name: "Ezekiel",
|
|
995
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
996
|
+
chapters: 48,
|
|
997
|
+
verses: [
|
|
998
|
+
28,
|
|
999
|
+
10,
|
|
1000
|
+
27,
|
|
1001
|
+
17,
|
|
1002
|
+
17,
|
|
1003
|
+
14,
|
|
1004
|
+
27,
|
|
1005
|
+
18,
|
|
1006
|
+
11,
|
|
1007
|
+
22,
|
|
1008
|
+
25,
|
|
1009
|
+
28,
|
|
1010
|
+
23,
|
|
1011
|
+
23,
|
|
1012
|
+
8,
|
|
1013
|
+
63,
|
|
1014
|
+
24,
|
|
1015
|
+
32,
|
|
1016
|
+
14,
|
|
1017
|
+
49,
|
|
1018
|
+
32,
|
|
1019
|
+
31,
|
|
1020
|
+
49,
|
|
1021
|
+
27,
|
|
1022
|
+
17,
|
|
1023
|
+
21,
|
|
1024
|
+
36,
|
|
1025
|
+
26,
|
|
1026
|
+
21,
|
|
1027
|
+
26,
|
|
1028
|
+
18,
|
|
1029
|
+
32,
|
|
1030
|
+
33,
|
|
1031
|
+
31,
|
|
1032
|
+
15,
|
|
1033
|
+
38,
|
|
1034
|
+
28,
|
|
1035
|
+
23,
|
|
1036
|
+
29,
|
|
1037
|
+
49,
|
|
1038
|
+
26,
|
|
1039
|
+
20,
|
|
1040
|
+
27,
|
|
1041
|
+
31,
|
|
1042
|
+
25,
|
|
1043
|
+
24,
|
|
1044
|
+
23,
|
|
1045
|
+
35
|
|
1046
|
+
]
|
|
1047
|
+
},
|
|
1048
|
+
27: {
|
|
1049
|
+
number: 27,
|
|
1050
|
+
name: "Daniel",
|
|
1051
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1052
|
+
chapters: 12,
|
|
1053
|
+
verses: [21, 49, 30, 37, 31, 28, 28, 27, 27, 21, 45, 13]
|
|
1054
|
+
},
|
|
1055
|
+
28: {
|
|
1056
|
+
number: 28,
|
|
1057
|
+
name: "Hosea",
|
|
1058
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1059
|
+
chapters: 14,
|
|
1060
|
+
verses: [11, 23, 5, 19, 15, 11, 16, 14, 17, 15, 12, 14, 16, 9]
|
|
1061
|
+
},
|
|
1062
|
+
29: {
|
|
1063
|
+
number: 29,
|
|
1064
|
+
name: "Joel",
|
|
1065
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1066
|
+
chapters: 3,
|
|
1067
|
+
verses: [20, 32, 21]
|
|
1068
|
+
},
|
|
1069
|
+
30: {
|
|
1070
|
+
number: 30,
|
|
1071
|
+
name: "Amos",
|
|
1072
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1073
|
+
chapters: 9,
|
|
1074
|
+
verses: [15, 16, 15, 13, 27, 14, 17, 14, 15]
|
|
1075
|
+
},
|
|
1076
|
+
31: {
|
|
1077
|
+
number: 31,
|
|
1078
|
+
name: "Obadiah",
|
|
1079
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1080
|
+
chapters: 1,
|
|
1081
|
+
verses: [21]
|
|
1082
|
+
},
|
|
1083
|
+
32: {
|
|
1084
|
+
number: 32,
|
|
1085
|
+
name: "Jonah",
|
|
1086
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1087
|
+
chapters: 4,
|
|
1088
|
+
verses: [17, 10, 10, 11]
|
|
1089
|
+
},
|
|
1090
|
+
33: {
|
|
1091
|
+
number: 33,
|
|
1092
|
+
name: "Micah",
|
|
1093
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1094
|
+
chapters: 7,
|
|
1095
|
+
verses: [16, 13, 12, 13, 15, 16, 20]
|
|
1096
|
+
},
|
|
1097
|
+
34: {
|
|
1098
|
+
number: 34,
|
|
1099
|
+
name: "Nahum",
|
|
1100
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1101
|
+
chapters: 3,
|
|
1102
|
+
verses: [15, 13, 19]
|
|
1103
|
+
},
|
|
1104
|
+
35: {
|
|
1105
|
+
number: 35,
|
|
1106
|
+
name: "Habakkuk",
|
|
1107
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1108
|
+
chapters: 3,
|
|
1109
|
+
verses: [17, 20, 19]
|
|
1110
|
+
},
|
|
1111
|
+
36: {
|
|
1112
|
+
number: 36,
|
|
1113
|
+
name: "Zephaniah",
|
|
1114
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1115
|
+
chapters: 3,
|
|
1116
|
+
verses: [18, 15, 20]
|
|
1117
|
+
},
|
|
1118
|
+
37: {
|
|
1119
|
+
number: 37,
|
|
1120
|
+
name: "Haggai",
|
|
1121
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1122
|
+
chapters: 2,
|
|
1123
|
+
verses: [15, 23]
|
|
1124
|
+
},
|
|
1125
|
+
38: {
|
|
1126
|
+
number: 38,
|
|
1127
|
+
name: "Zechariah",
|
|
1128
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1129
|
+
chapters: 14,
|
|
1130
|
+
verses: [21, 13, 10, 14, 11, 15, 14, 23, 17, 12, 17, 14, 9, 21]
|
|
1131
|
+
},
|
|
1132
|
+
39: {
|
|
1133
|
+
number: 39,
|
|
1134
|
+
name: "Malachi",
|
|
1135
|
+
testament: "OT" /* OLD_TESTAMENT */,
|
|
1136
|
+
chapters: 4,
|
|
1137
|
+
verses: [14, 17, 18, 6]
|
|
1138
|
+
},
|
|
1139
|
+
40: {
|
|
1140
|
+
number: 40,
|
|
1141
|
+
name: "Matthew",
|
|
1142
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1143
|
+
chapters: 28,
|
|
1144
|
+
verses: [
|
|
1145
|
+
25,
|
|
1146
|
+
23,
|
|
1147
|
+
17,
|
|
1148
|
+
25,
|
|
1149
|
+
48,
|
|
1150
|
+
34,
|
|
1151
|
+
29,
|
|
1152
|
+
34,
|
|
1153
|
+
38,
|
|
1154
|
+
42,
|
|
1155
|
+
30,
|
|
1156
|
+
50,
|
|
1157
|
+
58,
|
|
1158
|
+
36,
|
|
1159
|
+
39,
|
|
1160
|
+
28,
|
|
1161
|
+
27,
|
|
1162
|
+
35,
|
|
1163
|
+
30,
|
|
1164
|
+
34,
|
|
1165
|
+
46,
|
|
1166
|
+
46,
|
|
1167
|
+
39,
|
|
1168
|
+
51,
|
|
1169
|
+
46,
|
|
1170
|
+
75,
|
|
1171
|
+
66,
|
|
1172
|
+
20
|
|
1173
|
+
]
|
|
1174
|
+
},
|
|
1175
|
+
41: {
|
|
1176
|
+
number: 41,
|
|
1177
|
+
name: "Mark",
|
|
1178
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1179
|
+
chapters: 16,
|
|
1180
|
+
verses: [45, 28, 35, 41, 43, 56, 37, 38, 50, 52, 33, 44, 37, 72, 47, 20]
|
|
1181
|
+
},
|
|
1182
|
+
42: {
|
|
1183
|
+
number: 42,
|
|
1184
|
+
name: "Luke",
|
|
1185
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1186
|
+
chapters: 24,
|
|
1187
|
+
verses: [
|
|
1188
|
+
80,
|
|
1189
|
+
52,
|
|
1190
|
+
38,
|
|
1191
|
+
44,
|
|
1192
|
+
39,
|
|
1193
|
+
49,
|
|
1194
|
+
50,
|
|
1195
|
+
56,
|
|
1196
|
+
62,
|
|
1197
|
+
42,
|
|
1198
|
+
54,
|
|
1199
|
+
59,
|
|
1200
|
+
35,
|
|
1201
|
+
35,
|
|
1202
|
+
32,
|
|
1203
|
+
31,
|
|
1204
|
+
37,
|
|
1205
|
+
43,
|
|
1206
|
+
48,
|
|
1207
|
+
47,
|
|
1208
|
+
38,
|
|
1209
|
+
71,
|
|
1210
|
+
56,
|
|
1211
|
+
53
|
|
1212
|
+
]
|
|
1213
|
+
},
|
|
1214
|
+
43: {
|
|
1215
|
+
number: 43,
|
|
1216
|
+
name: "John",
|
|
1217
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1218
|
+
chapters: 21,
|
|
1219
|
+
verses: [51, 25, 36, 54, 47, 71, 53, 59, 41, 42, 57, 50, 38, 31, 27, 33, 26, 40, 42, 31, 25]
|
|
1220
|
+
},
|
|
1221
|
+
44: {
|
|
1222
|
+
number: 44,
|
|
1223
|
+
name: "Acts",
|
|
1224
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1225
|
+
chapters: 28,
|
|
1226
|
+
verses: [
|
|
1227
|
+
26,
|
|
1228
|
+
47,
|
|
1229
|
+
26,
|
|
1230
|
+
37,
|
|
1231
|
+
42,
|
|
1232
|
+
15,
|
|
1233
|
+
60,
|
|
1234
|
+
40,
|
|
1235
|
+
43,
|
|
1236
|
+
48,
|
|
1237
|
+
30,
|
|
1238
|
+
25,
|
|
1239
|
+
52,
|
|
1240
|
+
28,
|
|
1241
|
+
41,
|
|
1242
|
+
40,
|
|
1243
|
+
34,
|
|
1244
|
+
28,
|
|
1245
|
+
41,
|
|
1246
|
+
38,
|
|
1247
|
+
40,
|
|
1248
|
+
30,
|
|
1249
|
+
35,
|
|
1250
|
+
27,
|
|
1251
|
+
27,
|
|
1252
|
+
32,
|
|
1253
|
+
44,
|
|
1254
|
+
31
|
|
1255
|
+
]
|
|
1256
|
+
},
|
|
1257
|
+
45: {
|
|
1258
|
+
number: 45,
|
|
1259
|
+
name: "Romans",
|
|
1260
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1261
|
+
chapters: 16,
|
|
1262
|
+
verses: [32, 29, 31, 25, 21, 23, 25, 39, 33, 21, 36, 21, 14, 23, 33, 27]
|
|
1263
|
+
},
|
|
1264
|
+
46: {
|
|
1265
|
+
number: 46,
|
|
1266
|
+
name: "1 Corinthians",
|
|
1267
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1268
|
+
chapters: 16,
|
|
1269
|
+
verses: [31, 16, 23, 21, 13, 20, 40, 13, 27, 33, 34, 31, 13, 40, 58, 24]
|
|
1270
|
+
},
|
|
1271
|
+
47: {
|
|
1272
|
+
number: 47,
|
|
1273
|
+
name: "2 Corinthians",
|
|
1274
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1275
|
+
chapters: 13,
|
|
1276
|
+
verses: [24, 17, 18, 18, 21, 18, 16, 24, 15, 18, 33, 21, 14]
|
|
1277
|
+
},
|
|
1278
|
+
48: {
|
|
1279
|
+
number: 48,
|
|
1280
|
+
name: "Galatians",
|
|
1281
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1282
|
+
chapters: 6,
|
|
1283
|
+
verses: [24, 21, 29, 31, 26, 18]
|
|
1284
|
+
},
|
|
1285
|
+
49: {
|
|
1286
|
+
number: 49,
|
|
1287
|
+
name: "Ephesians",
|
|
1288
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1289
|
+
chapters: 6,
|
|
1290
|
+
verses: [23, 22, 21, 32, 33, 24]
|
|
1291
|
+
},
|
|
1292
|
+
50: {
|
|
1293
|
+
number: 50,
|
|
1294
|
+
name: "Philippians",
|
|
1295
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1296
|
+
chapters: 4,
|
|
1297
|
+
verses: [30, 30, 21, 23]
|
|
1298
|
+
},
|
|
1299
|
+
51: {
|
|
1300
|
+
number: 51,
|
|
1301
|
+
name: "Colossians",
|
|
1302
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1303
|
+
chapters: 4,
|
|
1304
|
+
verses: [29, 23, 25, 18]
|
|
1305
|
+
},
|
|
1306
|
+
52: {
|
|
1307
|
+
number: 52,
|
|
1308
|
+
name: "1 Thessalonians",
|
|
1309
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1310
|
+
chapters: 5,
|
|
1311
|
+
verses: [10, 20, 13, 18, 28]
|
|
1312
|
+
},
|
|
1313
|
+
53: {
|
|
1314
|
+
number: 53,
|
|
1315
|
+
name: "2 Thessalonians",
|
|
1316
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1317
|
+
chapters: 3,
|
|
1318
|
+
verses: [12, 17, 18]
|
|
1319
|
+
},
|
|
1320
|
+
54: {
|
|
1321
|
+
number: 54,
|
|
1322
|
+
name: "1 Timothy",
|
|
1323
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1324
|
+
chapters: 6,
|
|
1325
|
+
verses: [20, 15, 16, 16, 25, 21]
|
|
1326
|
+
},
|
|
1327
|
+
55: {
|
|
1328
|
+
number: 55,
|
|
1329
|
+
name: "2 Timothy",
|
|
1330
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1331
|
+
chapters: 4,
|
|
1332
|
+
verses: [18, 26, 17, 22]
|
|
1333
|
+
},
|
|
1334
|
+
56: {
|
|
1335
|
+
number: 56,
|
|
1336
|
+
name: "Titus",
|
|
1337
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1338
|
+
chapters: 3,
|
|
1339
|
+
verses: [16, 15, 15]
|
|
1340
|
+
},
|
|
1341
|
+
57: {
|
|
1342
|
+
number: 57,
|
|
1343
|
+
name: "Philemon",
|
|
1344
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1345
|
+
chapters: 1,
|
|
1346
|
+
verses: [25]
|
|
1347
|
+
},
|
|
1348
|
+
58: {
|
|
1349
|
+
number: 58,
|
|
1350
|
+
name: "Hebrews",
|
|
1351
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1352
|
+
chapters: 13,
|
|
1353
|
+
verses: [14, 18, 19, 16, 14, 20, 28, 13, 28, 39, 40, 29, 25]
|
|
1354
|
+
},
|
|
1355
|
+
59: {
|
|
1356
|
+
number: 59,
|
|
1357
|
+
name: "James",
|
|
1358
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1359
|
+
chapters: 5,
|
|
1360
|
+
verses: [27, 26, 18, 17, 20]
|
|
1361
|
+
},
|
|
1362
|
+
60: {
|
|
1363
|
+
number: 60,
|
|
1364
|
+
name: "1 Peter",
|
|
1365
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1366
|
+
chapters: 5,
|
|
1367
|
+
verses: [25, 25, 22, 19, 14]
|
|
1368
|
+
},
|
|
1369
|
+
61: {
|
|
1370
|
+
number: 61,
|
|
1371
|
+
name: "2 Peter",
|
|
1372
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1373
|
+
chapters: 3,
|
|
1374
|
+
verses: [21, 22, 18]
|
|
1375
|
+
},
|
|
1376
|
+
62: {
|
|
1377
|
+
number: 62,
|
|
1378
|
+
name: "1 John",
|
|
1379
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1380
|
+
chapters: 5,
|
|
1381
|
+
verses: [10, 29, 24, 21, 21]
|
|
1382
|
+
},
|
|
1383
|
+
63: {
|
|
1384
|
+
number: 63,
|
|
1385
|
+
name: "2 John",
|
|
1386
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1387
|
+
chapters: 1,
|
|
1388
|
+
verses: [13]
|
|
1389
|
+
},
|
|
1390
|
+
64: {
|
|
1391
|
+
number: 64,
|
|
1392
|
+
name: "3 John",
|
|
1393
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1394
|
+
chapters: 1,
|
|
1395
|
+
verses: [14]
|
|
1396
|
+
},
|
|
1397
|
+
65: {
|
|
1398
|
+
number: 65,
|
|
1399
|
+
name: "Jude",
|
|
1400
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1401
|
+
chapters: 1,
|
|
1402
|
+
verses: [25]
|
|
1403
|
+
},
|
|
1404
|
+
66: {
|
|
1405
|
+
number: 66,
|
|
1406
|
+
name: "Revelation",
|
|
1407
|
+
testament: "NT" /* NEW_TESTAMENT */,
|
|
1408
|
+
chapters: 22,
|
|
1409
|
+
verses: [20, 29, 22, 11, 14, 17, 17, 13, 21, 11, 19, 17, 18, 20, 8, 21, 18, 24, 21, 15, 27, 21]
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
var BOOK_NAMES = Object.fromEntries(
|
|
1413
|
+
Object.values(BIBLE_STRUCTURE).map((book) => [book.number, book.name])
|
|
1414
|
+
);
|
|
1415
|
+
var BOOK_NUMBERS = Object.fromEntries(
|
|
1416
|
+
Object.values(BIBLE_STRUCTURE).map((book) => [book.name.toLowerCase(), book.number])
|
|
1417
|
+
);
|
|
1418
|
+
var BookName = /* @__PURE__ */ ((BookName2) => {
|
|
1419
|
+
BookName2["GENESIS"] = "Genesis";
|
|
1420
|
+
BookName2["EXODUS"] = "Exodus";
|
|
1421
|
+
BookName2["LEVITICUS"] = "Leviticus";
|
|
1422
|
+
BookName2["NUMBERS"] = "Numbers";
|
|
1423
|
+
BookName2["DEUTERONOMY"] = "Deuteronomy";
|
|
1424
|
+
BookName2["JOSHUA"] = "Joshua";
|
|
1425
|
+
BookName2["JUDGES"] = "Judges";
|
|
1426
|
+
BookName2["RUTH"] = "Ruth";
|
|
1427
|
+
BookName2["SAMUEL_1"] = "1 Samuel";
|
|
1428
|
+
BookName2["SAMUEL_2"] = "2 Samuel";
|
|
1429
|
+
BookName2["KINGS_1"] = "1 Kings";
|
|
1430
|
+
BookName2["KINGS_2"] = "2 Kings";
|
|
1431
|
+
BookName2["CHRONICLES_1"] = "1 Chronicles";
|
|
1432
|
+
BookName2["CHRONICLES_2"] = "2 Chronicles";
|
|
1433
|
+
BookName2["EZRA"] = "Ezra";
|
|
1434
|
+
BookName2["NEHEMIAH"] = "Nehemiah";
|
|
1435
|
+
BookName2["ESTHER"] = "Esther";
|
|
1436
|
+
BookName2["JOB"] = "Job";
|
|
1437
|
+
BookName2["PSALMS"] = "Psalms";
|
|
1438
|
+
BookName2["PROVERBS"] = "Proverbs";
|
|
1439
|
+
BookName2["ECCLESIASTES"] = "Ecclesiastes";
|
|
1440
|
+
BookName2["SONG_OF_SONGS"] = "Song of Songs";
|
|
1441
|
+
BookName2["ISAIAH"] = "Isaiah";
|
|
1442
|
+
BookName2["JEREMIAH"] = "Jeremiah";
|
|
1443
|
+
BookName2["LAMENTATIONS"] = "Lamentations";
|
|
1444
|
+
BookName2["EZEKIEL"] = "Ezekiel";
|
|
1445
|
+
BookName2["DANIEL"] = "Daniel";
|
|
1446
|
+
BookName2["HOSEA"] = "Hosea";
|
|
1447
|
+
BookName2["JOEL"] = "Joel";
|
|
1448
|
+
BookName2["AMOS"] = "Amos";
|
|
1449
|
+
BookName2["OBADIAH"] = "Obadiah";
|
|
1450
|
+
BookName2["JONAH"] = "Jonah";
|
|
1451
|
+
BookName2["MICAH"] = "Micah";
|
|
1452
|
+
BookName2["NAHUM"] = "Nahum";
|
|
1453
|
+
BookName2["HABAKKUK"] = "Habakkuk";
|
|
1454
|
+
BookName2["ZEPHANIAH"] = "Zephaniah";
|
|
1455
|
+
BookName2["HAGGAI"] = "Haggai";
|
|
1456
|
+
BookName2["ZECHARIAH"] = "Zechariah";
|
|
1457
|
+
BookName2["MALACHI"] = "Malachi";
|
|
1458
|
+
BookName2["MATTHEW"] = "Matthew";
|
|
1459
|
+
BookName2["MARK"] = "Mark";
|
|
1460
|
+
BookName2["LUKE"] = "Luke";
|
|
1461
|
+
BookName2["JOHN"] = "John";
|
|
1462
|
+
BookName2["ACTS"] = "Acts";
|
|
1463
|
+
BookName2["ROMANS"] = "Romans";
|
|
1464
|
+
BookName2["CORINTHIANS_1"] = "1 Corinthians";
|
|
1465
|
+
BookName2["CORINTHIANS_2"] = "2 Corinthians";
|
|
1466
|
+
BookName2["GALATIANS"] = "Galatians";
|
|
1467
|
+
BookName2["EPHESIANS"] = "Ephesians";
|
|
1468
|
+
BookName2["PHILIPPIANS"] = "Philippians";
|
|
1469
|
+
BookName2["COLOSSIANS"] = "Colossians";
|
|
1470
|
+
BookName2["THESSALONIANS_1"] = "1 Thessalonians";
|
|
1471
|
+
BookName2["THESSALONIANS_2"] = "2 Thessalonians";
|
|
1472
|
+
BookName2["TIMOTHY_1"] = "1 Timothy";
|
|
1473
|
+
BookName2["TIMOTHY_2"] = "2 Timothy";
|
|
1474
|
+
BookName2["TITUS"] = "Titus";
|
|
1475
|
+
BookName2["PHILEMON"] = "Philemon";
|
|
1476
|
+
BookName2["HEBREWS"] = "Hebrews";
|
|
1477
|
+
BookName2["JAMES"] = "James";
|
|
1478
|
+
BookName2["PETER_1"] = "1 Peter";
|
|
1479
|
+
BookName2["PETER_2"] = "2 Peter";
|
|
1480
|
+
BookName2["JOHN_1"] = "1 John";
|
|
1481
|
+
BookName2["JOHN_2"] = "2 John";
|
|
1482
|
+
BookName2["JOHN_3"] = "3 John";
|
|
1483
|
+
BookName2["JUDE"] = "Jude";
|
|
1484
|
+
BookName2["REVELATION"] = "Revelation";
|
|
1485
|
+
return BookName2;
|
|
1486
|
+
})(BookName || {});
|
|
1487
|
+
var VerseReferenceSchema = zod.z.object({
|
|
1488
|
+
bookNumber: zod.z.number().int().min(1).max(66),
|
|
1489
|
+
chapter: zod.z.number().int().min(1),
|
|
1490
|
+
verse: zod.z.number().int().min(1)
|
|
1491
|
+
}).refine(
|
|
1492
|
+
(data) => {
|
|
1493
|
+
const bookInfo = BIBLE_STRUCTURE[data.bookNumber];
|
|
1494
|
+
if (!bookInfo) return false;
|
|
1495
|
+
return data.chapter <= bookInfo.chapters;
|
|
1496
|
+
},
|
|
1497
|
+
(data) => {
|
|
1498
|
+
const bookInfo = BIBLE_STRUCTURE[data.bookNumber];
|
|
1499
|
+
const bookName = BOOK_NAMES[data.bookNumber];
|
|
1500
|
+
return {
|
|
1501
|
+
message: `${bookName} only has ${bookInfo?.chapters} chapters, but chapter ${data.chapter} was requested`,
|
|
1502
|
+
path: ["chapter"]
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
).refine(
|
|
1506
|
+
(data) => {
|
|
1507
|
+
const bookInfo = BIBLE_STRUCTURE[data.bookNumber];
|
|
1508
|
+
if (!bookInfo) return false;
|
|
1509
|
+
const maxVerse = bookInfo.verses[data.chapter - 1];
|
|
1510
|
+
if (!maxVerse) return false;
|
|
1511
|
+
return data.verse <= maxVerse;
|
|
1512
|
+
},
|
|
1513
|
+
(data) => {
|
|
1514
|
+
const bookInfo = BIBLE_STRUCTURE[data.bookNumber];
|
|
1515
|
+
const bookName = BOOK_NAMES[data.bookNumber];
|
|
1516
|
+
const maxVerse = bookInfo?.verses[data.chapter - 1];
|
|
1517
|
+
return {
|
|
1518
|
+
message: `${bookName} ${data.chapter} only has ${maxVerse} verses, but verse ${data.verse} was requested`,
|
|
1519
|
+
path: ["verse"]
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
);
|
|
1523
|
+
function createVerseReference(data) {
|
|
1524
|
+
const validated = VerseReferenceSchema.parse(data);
|
|
1525
|
+
return {
|
|
1526
|
+
...validated,
|
|
1527
|
+
get bookName() {
|
|
1528
|
+
return BookName[BOOK_NAMES[this.bookNumber]] || BOOK_NAMES[this.bookNumber];
|
|
1529
|
+
},
|
|
1530
|
+
toString() {
|
|
1531
|
+
return `${BOOK_NAMES[this.bookNumber]} ${this.chapter}:${this.verse}`;
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
var TextSegmentSchema = zod.z.object({
|
|
1536
|
+
text: zod.z.string(),
|
|
1537
|
+
isRedLetter: zod.z.boolean().default(false),
|
|
1538
|
+
// Words of Jesus in red
|
|
1539
|
+
isItalic: zod.z.boolean().default(false),
|
|
1540
|
+
// Italicized text (clarifications)
|
|
1541
|
+
isBold: zod.z.boolean().default(false),
|
|
1542
|
+
// Bold text
|
|
1543
|
+
isSmallCaps: zod.z.boolean().default(false)
|
|
1544
|
+
// LORD (Yahweh) in small caps
|
|
1545
|
+
});
|
|
1546
|
+
var VerseContentSchema = zod.z.object({
|
|
1547
|
+
reference: VerseReferenceSchema,
|
|
1548
|
+
verseNumber: zod.z.number().int().min(1),
|
|
1549
|
+
segments: zod.z.array(TextSegmentSchema),
|
|
1550
|
+
hasSubheading: zod.z.boolean().default(false),
|
|
1551
|
+
subheadingText: zod.z.string().nullable().default(null),
|
|
1552
|
+
isPoetry: zod.z.boolean().default(false),
|
|
1553
|
+
isProse: zod.z.boolean().default(false),
|
|
1554
|
+
chapterStart: zod.z.boolean().default(false)
|
|
1555
|
+
// First verse of chapter
|
|
1556
|
+
});
|
|
1557
|
+
function createVerseContent(data) {
|
|
1558
|
+
const validated = VerseContentSchema.parse(data);
|
|
1559
|
+
const reference = createVerseReference(validated.reference);
|
|
1560
|
+
return {
|
|
1561
|
+
...validated,
|
|
1562
|
+
reference,
|
|
1563
|
+
get plainText() {
|
|
1564
|
+
return this.segments.map((seg) => seg.text).join(" ");
|
|
1565
|
+
},
|
|
1566
|
+
get formattedText() {
|
|
1567
|
+
const parts = this.segments.map((seg) => {
|
|
1568
|
+
let text = seg.text;
|
|
1569
|
+
if (seg.isItalic) text = `[${text}]`;
|
|
1570
|
+
if (seg.isRedLetter) text = `"${text}"`;
|
|
1571
|
+
return text;
|
|
1572
|
+
});
|
|
1573
|
+
return parts.join(" ");
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
var PassageSchema = zod.z.object({
|
|
1578
|
+
fromRef: VerseReferenceSchema,
|
|
1579
|
+
toRef: VerseReferenceSchema,
|
|
1580
|
+
title: zod.z.string(),
|
|
1581
|
+
verses: zod.z.array(VerseContentSchema)
|
|
1582
|
+
});
|
|
1583
|
+
function createPassage(data) {
|
|
1584
|
+
const validated = PassageSchema.parse(data);
|
|
1585
|
+
const fromRef = createVerseReference(validated.fromRef);
|
|
1586
|
+
const toRef = createVerseReference(validated.toRef);
|
|
1587
|
+
const verses = validated.verses.map((v) => createVerseContent(v));
|
|
1588
|
+
return {
|
|
1589
|
+
...validated,
|
|
1590
|
+
fromRef,
|
|
1591
|
+
toRef,
|
|
1592
|
+
verses,
|
|
1593
|
+
get isSingleVerse() {
|
|
1594
|
+
return this.fromRef.bookNumber === this.toRef.bookNumber && this.fromRef.chapter === this.toRef.chapter && this.fromRef.verse === this.toRef.verse;
|
|
1595
|
+
},
|
|
1596
|
+
get verseCount() {
|
|
1597
|
+
return this.verses.length;
|
|
1598
|
+
}
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
var SearchResponseSchema = zod.z.object({
|
|
1602
|
+
query: zod.z.string(),
|
|
1603
|
+
matchCount: zod.z.number().int().min(0),
|
|
1604
|
+
passages: zod.z.array(PassageSchema),
|
|
1605
|
+
durationMs: zod.z.number().int().min(0),
|
|
1606
|
+
timestamp: zod.z.number().int(),
|
|
1607
|
+
// Optional metadata for text searches
|
|
1608
|
+
totalCount: zod.z.number().int().min(0).optional(),
|
|
1609
|
+
filteredCount: zod.z.number().int().min(0).optional(),
|
|
1610
|
+
countsByBook: zod.z.record(zod.z.string(), zod.z.number()).optional(),
|
|
1611
|
+
countsBySection: zod.z.record(zod.z.string(), zod.z.number()).optional()
|
|
1612
|
+
});
|
|
1613
|
+
function createSearchResponse(data) {
|
|
1614
|
+
const validated = SearchResponseSchema.parse(data);
|
|
1615
|
+
const passages = validated.passages.map((p) => createPassage(p));
|
|
1616
|
+
return {
|
|
1617
|
+
...validated,
|
|
1618
|
+
passages,
|
|
1619
|
+
get passageCount() {
|
|
1620
|
+
return this.passages.length;
|
|
1621
|
+
},
|
|
1622
|
+
get totalVerses() {
|
|
1623
|
+
return this.passages.reduce((sum, p) => sum + p.verseCount, 0);
|
|
1624
|
+
},
|
|
1625
|
+
get hasSearchMetadata() {
|
|
1626
|
+
return this.totalCount !== void 0;
|
|
1627
|
+
}
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
// src/mcp/resources.ts
|
|
1632
|
+
function registerResources(server) {
|
|
1633
|
+
server.registerResource(
|
|
1634
|
+
"books",
|
|
1635
|
+
"bible://books",
|
|
1636
|
+
{
|
|
1637
|
+
title: "Bible Books",
|
|
1638
|
+
description: "List of all 66 books in the Bible",
|
|
1639
|
+
mimeType: "application/json"
|
|
1640
|
+
},
|
|
1641
|
+
async (uri) => {
|
|
1642
|
+
const books = Object.values(BIBLE_STRUCTURE).map(
|
|
1643
|
+
(bookInfo) => ({
|
|
1644
|
+
name: bookInfo.name,
|
|
1645
|
+
testament: bookInfo.testament,
|
|
1646
|
+
chapters: bookInfo.chapters,
|
|
1647
|
+
verses: bookInfo.verses.reduce((sum, count) => sum + count, 0)
|
|
1648
|
+
})
|
|
1649
|
+
);
|
|
1650
|
+
return {
|
|
1651
|
+
contents: [
|
|
1652
|
+
{
|
|
1653
|
+
uri: uri.href,
|
|
1654
|
+
mimeType: "application/json",
|
|
1655
|
+
text: JSON.stringify(books, null, 2)
|
|
1656
|
+
}
|
|
1657
|
+
]
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
);
|
|
1661
|
+
server.registerResource(
|
|
1662
|
+
"structure",
|
|
1663
|
+
new mcp_js.ResourceTemplate("bible://structure/{book}", {
|
|
1664
|
+
list: void 0,
|
|
1665
|
+
complete: {
|
|
1666
|
+
book: (value) => {
|
|
1667
|
+
return Object.values(BookName).filter((bookName) => bookName.toLowerCase().startsWith(value.toLowerCase())).slice(0, 10);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
}),
|
|
1671
|
+
{
|
|
1672
|
+
title: "Bible Book Structure",
|
|
1673
|
+
description: "Chapter and verse counts for a specific book",
|
|
1674
|
+
mimeType: "application/json"
|
|
1675
|
+
},
|
|
1676
|
+
async (uri, { book }) => {
|
|
1677
|
+
const bookName = book;
|
|
1678
|
+
const bookEntry = Object.values(BIBLE_STRUCTURE).find(
|
|
1679
|
+
(b) => b.name.toLowerCase() === bookName.toLowerCase()
|
|
1680
|
+
);
|
|
1681
|
+
if (!bookEntry) {
|
|
1682
|
+
throw new Error(`Unknown book: ${bookName}`);
|
|
1683
|
+
}
|
|
1684
|
+
const data = {
|
|
1685
|
+
uri: uri.href,
|
|
1686
|
+
book: bookEntry.name,
|
|
1687
|
+
testament: bookEntry.testament,
|
|
1688
|
+
totalChapters: bookEntry.chapters,
|
|
1689
|
+
totalVerses: bookEntry.verses.reduce((sum, verses) => sum + verses, 0),
|
|
1690
|
+
chapters: bookEntry.verses.map((verses, index) => ({
|
|
1691
|
+
chapter: index + 1,
|
|
1692
|
+
verses
|
|
1693
|
+
}))
|
|
1694
|
+
};
|
|
1695
|
+
return {
|
|
1696
|
+
contents: [
|
|
1697
|
+
{
|
|
1698
|
+
uri: uri.href,
|
|
1699
|
+
mimeType: "application/json",
|
|
1700
|
+
text: JSON.stringify(data, null, 2)
|
|
1701
|
+
}
|
|
1702
|
+
]
|
|
1703
|
+
};
|
|
1704
|
+
}
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
// src/cache/memory.ts
|
|
1709
|
+
var MemoryCacheProvider = class {
|
|
1710
|
+
cache = /* @__PURE__ */ new Map();
|
|
1711
|
+
async get(key) {
|
|
1712
|
+
const entry = this.cache.get(key);
|
|
1713
|
+
if (!entry) {
|
|
1714
|
+
return void 0;
|
|
1715
|
+
}
|
|
1716
|
+
if (Date.now() > entry.expires) {
|
|
1717
|
+
this.cache.delete(key);
|
|
1718
|
+
return void 0;
|
|
1719
|
+
}
|
|
1720
|
+
return entry.data;
|
|
1721
|
+
}
|
|
1722
|
+
async set(key, value, ttl) {
|
|
1723
|
+
const expires = Date.now() + ttl * 1e3;
|
|
1724
|
+
this.cache.set(key, { data: value, expires });
|
|
1725
|
+
}
|
|
1726
|
+
/**
|
|
1727
|
+
* Clear all cache entries.
|
|
1728
|
+
*
|
|
1729
|
+
* Useful for testing or manual cache invalidation.
|
|
1730
|
+
*/
|
|
1731
|
+
clear() {
|
|
1732
|
+
this.cache.clear();
|
|
1733
|
+
}
|
|
1734
|
+
/**
|
|
1735
|
+
* Get the number of entries in the cache.
|
|
1736
|
+
*
|
|
1737
|
+
* Includes expired entries that haven't been accessed yet.
|
|
1738
|
+
*/
|
|
1739
|
+
size() {
|
|
1740
|
+
return this.cache.size;
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
|
|
1744
|
+
// src/cache/interface.ts
|
|
1745
|
+
var CacheTTL = {
|
|
1746
|
+
/** 1 month - for immutable Bible content (verses, passages, chapters) */
|
|
1747
|
+
BIBLE_CONTENT: 2592e3,
|
|
1748
|
+
/** 1 week - for search results that may change with API updates */
|
|
1749
|
+
SEARCH_RESULTS: 604800,
|
|
1750
|
+
/** 1 year - for static resources that never change */
|
|
1751
|
+
STATIC: 31536e3
|
|
1752
|
+
};
|
|
1753
|
+
|
|
1754
|
+
// src/exceptions.ts
|
|
1755
|
+
var LSBibleError = class extends Error {
|
|
1756
|
+
constructor(message) {
|
|
1757
|
+
super(message);
|
|
1758
|
+
this.name = "LSBibleError";
|
|
1759
|
+
if (Error.captureStackTrace) {
|
|
1760
|
+
Error.captureStackTrace(this, this.constructor);
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
var InvalidReferenceError = class extends LSBibleError {
|
|
1765
|
+
constructor(message) {
|
|
1766
|
+
super(message);
|
|
1767
|
+
this.name = "InvalidReferenceError";
|
|
1768
|
+
}
|
|
1769
|
+
};
|
|
1770
|
+
var APIError = class extends LSBibleError {
|
|
1771
|
+
constructor(message) {
|
|
1772
|
+
super(message);
|
|
1773
|
+
this.name = "APIError";
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
var BuildIDError = class extends LSBibleError {
|
|
1777
|
+
constructor(message) {
|
|
1778
|
+
super(message);
|
|
1779
|
+
this.name = "BuildIDError";
|
|
1780
|
+
}
|
|
1781
|
+
};
|
|
1782
|
+
function parseSearchResultHtml(html) {
|
|
1783
|
+
const { document } = linkedom.parseHTML(`<!DOCTYPE html><html><body>${html}</body></html>`);
|
|
1784
|
+
return document.body.textContent?.trim() ?? "";
|
|
1785
|
+
}
|
|
1786
|
+
function parsePassageHtml(html) {
|
|
1787
|
+
const { document } = linkedom.parseHTML(`<!DOCTYPE html><html><body>${html}</body></html>`);
|
|
1788
|
+
const verses = [];
|
|
1789
|
+
const verseSpans = document.querySelectorAll("span.verse");
|
|
1790
|
+
for (const verseSpan of verseSpans) {
|
|
1791
|
+
const verse = parseVerse(verseSpan);
|
|
1792
|
+
verses.push(verse);
|
|
1793
|
+
}
|
|
1794
|
+
return verses;
|
|
1795
|
+
}
|
|
1796
|
+
function parseVerse(verseSpan, _document) {
|
|
1797
|
+
const dataKey = verseSpan.getAttribute("data-key");
|
|
1798
|
+
if (!dataKey) {
|
|
1799
|
+
throw new Error("Verse span missing data-key attribute");
|
|
1800
|
+
}
|
|
1801
|
+
const reference = parseVerseReference(dataKey);
|
|
1802
|
+
const verseNumElem = verseSpan.querySelector("small[data-verse]");
|
|
1803
|
+
let verseNumber;
|
|
1804
|
+
if (verseNumElem) {
|
|
1805
|
+
verseNumber = Number.parseInt(verseNumElem.getAttribute("data-verse") ?? "0", 10);
|
|
1806
|
+
} else {
|
|
1807
|
+
verseNumber = reference.verse;
|
|
1808
|
+
}
|
|
1809
|
+
let hasSubheading = false;
|
|
1810
|
+
let subheadingText = null;
|
|
1811
|
+
const prevSibling = verseSpan.previousElementSibling;
|
|
1812
|
+
if (prevSibling?.classList.contains("subhead")) {
|
|
1813
|
+
hasSubheading = true;
|
|
1814
|
+
subheadingText = prevSibling.textContent?.trim() ?? null;
|
|
1815
|
+
}
|
|
1816
|
+
let currentNode = verseSpan;
|
|
1817
|
+
let isPoetry = false;
|
|
1818
|
+
while (currentNode) {
|
|
1819
|
+
if (currentNode.classList?.contains("poetry")) {
|
|
1820
|
+
isPoetry = true;
|
|
1821
|
+
break;
|
|
1822
|
+
}
|
|
1823
|
+
currentNode = currentNode.parentElement;
|
|
1824
|
+
}
|
|
1825
|
+
const isProse = verseSpan.querySelector(".prose") !== null;
|
|
1826
|
+
const chapterStart = verseSpan.querySelector(".chapter-number") !== null;
|
|
1827
|
+
const segments = extractSegments(verseSpan);
|
|
1828
|
+
return createVerseContent({
|
|
1829
|
+
reference,
|
|
1830
|
+
verseNumber,
|
|
1831
|
+
segments,
|
|
1832
|
+
hasSubheading,
|
|
1833
|
+
subheadingText,
|
|
1834
|
+
isPoetry,
|
|
1835
|
+
isProse,
|
|
1836
|
+
chapterStart
|
|
1837
|
+
});
|
|
1838
|
+
}
|
|
1839
|
+
function parseVerseReference(dataKey) {
|
|
1840
|
+
const parts = dataKey.split("-");
|
|
1841
|
+
if (parts.length !== 3) {
|
|
1842
|
+
throw new Error(`Invalid data-key format: ${dataKey}`);
|
|
1843
|
+
}
|
|
1844
|
+
const bookNumber = Number.parseInt(parts[0] ?? "0", 10);
|
|
1845
|
+
const chapter = Number.parseInt(parts[1] ?? "0", 10);
|
|
1846
|
+
const verse = Number.parseInt(parts[2] ?? "0", 10);
|
|
1847
|
+
return createVerseReference({ bookNumber, chapter, verse });
|
|
1848
|
+
}
|
|
1849
|
+
function extractSegments(element) {
|
|
1850
|
+
const segments = [];
|
|
1851
|
+
for (const smallElem of element.querySelectorAll("small[data-verse]")) {
|
|
1852
|
+
smallElem.remove();
|
|
1853
|
+
}
|
|
1854
|
+
for (const chapterElem of element.querySelectorAll(".chapter-number")) {
|
|
1855
|
+
chapterElem.remove();
|
|
1856
|
+
}
|
|
1857
|
+
for (const subheadElem of element.querySelectorAll(".subhead")) {
|
|
1858
|
+
subheadElem.remove();
|
|
1859
|
+
}
|
|
1860
|
+
extractTextNodes(element, segments);
|
|
1861
|
+
return segments;
|
|
1862
|
+
}
|
|
1863
|
+
function extractTextNodes(node, segments) {
|
|
1864
|
+
for (const child of node.childNodes) {
|
|
1865
|
+
if (child.nodeType === 3) {
|
|
1866
|
+
const text = child.textContent?.trim();
|
|
1867
|
+
if (!text) continue;
|
|
1868
|
+
let isRedLetter = false;
|
|
1869
|
+
let isItalic = false;
|
|
1870
|
+
let isBold = false;
|
|
1871
|
+
let isSmallCaps = false;
|
|
1872
|
+
let parent = child.parentElement;
|
|
1873
|
+
while (parent) {
|
|
1874
|
+
if (parent.classList.contains("red-letter")) {
|
|
1875
|
+
isRedLetter = true;
|
|
1876
|
+
}
|
|
1877
|
+
if (parent.tagName === "I" || parent.classList.contains("italic")) {
|
|
1878
|
+
isItalic = true;
|
|
1879
|
+
}
|
|
1880
|
+
if (parent.tagName === "B" || parent.classList.contains("bold")) {
|
|
1881
|
+
isBold = true;
|
|
1882
|
+
}
|
|
1883
|
+
if (parent.classList.contains("small-caps")) {
|
|
1884
|
+
isSmallCaps = true;
|
|
1885
|
+
}
|
|
1886
|
+
parent = parent.parentElement;
|
|
1887
|
+
}
|
|
1888
|
+
segments.push({
|
|
1889
|
+
text,
|
|
1890
|
+
isRedLetter,
|
|
1891
|
+
isItalic,
|
|
1892
|
+
isBold,
|
|
1893
|
+
isSmallCaps
|
|
1894
|
+
});
|
|
1895
|
+
} else if (child.nodeType === 1) {
|
|
1896
|
+
extractTextNodes(child, segments);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
// src/validators.ts
|
|
1902
|
+
function normalizeBookName(book) {
|
|
1903
|
+
if (typeof book === "string" && Object.values(BookName).includes(book)) {
|
|
1904
|
+
return book;
|
|
1905
|
+
}
|
|
1906
|
+
if (typeof book !== "string") {
|
|
1907
|
+
throw new InvalidReferenceError(`Invalid book type: ${typeof book}`);
|
|
1908
|
+
}
|
|
1909
|
+
const bookStr = book.trim();
|
|
1910
|
+
const bookLower = bookStr.toLowerCase();
|
|
1911
|
+
if (bookLower in BOOK_NUMBERS) {
|
|
1912
|
+
const bookNum = BOOK_NUMBERS[bookLower];
|
|
1913
|
+
if (bookNum) {
|
|
1914
|
+
return BIBLE_STRUCTURE[bookNum]?.name ?? book;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
const normalized = bookLower.split(/\s+/).join(" ");
|
|
1918
|
+
if (normalized in BOOK_NUMBERS) {
|
|
1919
|
+
const bookNum = BOOK_NUMBERS[normalized];
|
|
1920
|
+
if (bookNum) {
|
|
1921
|
+
return BIBLE_STRUCTURE[bookNum]?.name ?? book;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
if (/^\d/.test(bookLower)) {
|
|
1925
|
+
const spaced = bookLower.replace(/^(\d+)([a-z])/, "$1 $2");
|
|
1926
|
+
if (spaced in BOOK_NUMBERS) {
|
|
1927
|
+
const bookNum = BOOK_NUMBERS[spaced];
|
|
1928
|
+
if (bookNum) {
|
|
1929
|
+
return BIBLE_STRUCTURE[bookNum]?.name ?? book;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
throw new InvalidReferenceError(`Unknown book: ${book}`);
|
|
1934
|
+
}
|
|
1935
|
+
function getBookNumber(book) {
|
|
1936
|
+
const normalized = normalizeBookName(book);
|
|
1937
|
+
const bookNum = BOOK_NUMBERS[normalized.toLowerCase()];
|
|
1938
|
+
if (!bookNum) {
|
|
1939
|
+
throw new InvalidReferenceError(`Unknown book: ${book}`);
|
|
1940
|
+
}
|
|
1941
|
+
return bookNum;
|
|
1942
|
+
}
|
|
1943
|
+
function validateReference(book, chapter, verse) {
|
|
1944
|
+
try {
|
|
1945
|
+
const bookNumber = getBookNumber(book);
|
|
1946
|
+
return createVerseReference({
|
|
1947
|
+
bookNumber,
|
|
1948
|
+
chapter,
|
|
1949
|
+
verse
|
|
1950
|
+
});
|
|
1951
|
+
} catch (error) {
|
|
1952
|
+
if (error instanceof Error) {
|
|
1953
|
+
throw new InvalidReferenceError(error.message);
|
|
1954
|
+
}
|
|
1955
|
+
throw error;
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
// src/client.ts
|
|
1960
|
+
function getSdkVersion() {
|
|
1961
|
+
return "0.1.0";
|
|
1962
|
+
}
|
|
1963
|
+
function getUserAgent() {
|
|
1964
|
+
const version = getSdkVersion();
|
|
1965
|
+
const runtime = "Bun" in globalThis ? "Bun" : "Deno" in globalThis ? "Deno" : "Node.js";
|
|
1966
|
+
return `lsbible-typescript/${version} (${runtime}; +https://github.com/kdcokenny/lsbible)`;
|
|
1967
|
+
}
|
|
1968
|
+
var LSBibleClient = class _LSBibleClient {
|
|
1969
|
+
static BASE_URL = "https://read.lsbible.org";
|
|
1970
|
+
cacheProvider;
|
|
1971
|
+
cacheTtls;
|
|
1972
|
+
timeout;
|
|
1973
|
+
buildId;
|
|
1974
|
+
buildIdFetched;
|
|
1975
|
+
headers;
|
|
1976
|
+
/**
|
|
1977
|
+
* Create a new LSBible client.
|
|
1978
|
+
*
|
|
1979
|
+
* @param options - Client configuration options
|
|
1980
|
+
*/
|
|
1981
|
+
constructor(options = {}) {
|
|
1982
|
+
this.cacheProvider = options.cache?.provider ?? void 0;
|
|
1983
|
+
this.cacheTtls = {
|
|
1984
|
+
verse: options.cache?.ttl?.verse ?? CacheTTL.BIBLE_CONTENT,
|
|
1985
|
+
passage: options.cache?.ttl?.passage ?? CacheTTL.BIBLE_CONTENT,
|
|
1986
|
+
chapter: options.cache?.ttl?.chapter ?? CacheTTL.BIBLE_CONTENT,
|
|
1987
|
+
search: options.cache?.ttl?.search ?? CacheTTL.SEARCH_RESULTS
|
|
1988
|
+
};
|
|
1989
|
+
this.timeout = (options.timeout ?? 30) * 1e3;
|
|
1990
|
+
this.buildId = options.buildId;
|
|
1991
|
+
this.buildIdFetched = options.buildId !== void 0;
|
|
1992
|
+
this.headers = {
|
|
1993
|
+
"User-Agent": getUserAgent(),
|
|
1994
|
+
Accept: "*/*",
|
|
1995
|
+
...options.headers
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
/**
|
|
1999
|
+
* Get the Next.js build ID.
|
|
2000
|
+
*
|
|
2001
|
+
* Strategies:
|
|
2002
|
+
* 1. Use cached/provided build ID
|
|
2003
|
+
* 2. Extract from homepage HTML (__NEXT_DATA__ script)
|
|
2004
|
+
* 3. Try to find it in script tags
|
|
2005
|
+
*
|
|
2006
|
+
* @throws BuildIDError if build ID cannot be determined
|
|
2007
|
+
*/
|
|
2008
|
+
async getBuildId() {
|
|
2009
|
+
if (this.buildId && this.buildIdFetched) {
|
|
2010
|
+
return this.buildId;
|
|
2011
|
+
}
|
|
2012
|
+
try {
|
|
2013
|
+
const controller = new AbortController();
|
|
2014
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
2015
|
+
const response = await fetch(_LSBibleClient.BASE_URL, {
|
|
2016
|
+
signal: controller.signal,
|
|
2017
|
+
headers: this.headers
|
|
2018
|
+
});
|
|
2019
|
+
clearTimeout(timeoutId);
|
|
2020
|
+
if (!response.ok) {
|
|
2021
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
2022
|
+
}
|
|
2023
|
+
const html = await response.text();
|
|
2024
|
+
const buildIdMatch = html.match(/"buildId":"([^"]+)"/);
|
|
2025
|
+
if (buildIdMatch?.[1]) {
|
|
2026
|
+
this.buildId = buildIdMatch[1];
|
|
2027
|
+
this.buildIdFetched = true;
|
|
2028
|
+
return this.buildId;
|
|
2029
|
+
}
|
|
2030
|
+
const scriptMatch = html.match(/\/_next\/data\/([^/]+)\//);
|
|
2031
|
+
if (scriptMatch?.[1]) {
|
|
2032
|
+
this.buildId = scriptMatch[1];
|
|
2033
|
+
this.buildIdFetched = true;
|
|
2034
|
+
return this.buildId;
|
|
2035
|
+
}
|
|
2036
|
+
} catch (error) {
|
|
2037
|
+
throw new BuildIDError(
|
|
2038
|
+
`Failed to fetch build ID: ${error instanceof Error ? error.message : String(error)}`
|
|
2039
|
+
);
|
|
2040
|
+
}
|
|
2041
|
+
throw new BuildIDError("Could not determine build ID from homepage");
|
|
2042
|
+
}
|
|
2043
|
+
/**
|
|
2044
|
+
* Cache wrapper for async operations.
|
|
2045
|
+
*
|
|
2046
|
+
* @param key - Cache key
|
|
2047
|
+
* @param ttl - Time to live in seconds
|
|
2048
|
+
* @param fetcher - Function to fetch fresh data
|
|
2049
|
+
* @returns Cached or fresh data
|
|
2050
|
+
*/
|
|
2051
|
+
async withCache(key, ttl, fetcher) {
|
|
2052
|
+
if (!this.cacheProvider) {
|
|
2053
|
+
return fetcher();
|
|
2054
|
+
}
|
|
2055
|
+
const cached = await this.cacheProvider.get(key);
|
|
2056
|
+
if (cached !== void 0) {
|
|
2057
|
+
return cached;
|
|
2058
|
+
}
|
|
2059
|
+
const data = await fetcher();
|
|
2060
|
+
await this.cacheProvider.set(key, data, ttl);
|
|
2061
|
+
return data;
|
|
2062
|
+
}
|
|
2063
|
+
/**
|
|
2064
|
+
* Make a request to the LSBible API.
|
|
2065
|
+
*
|
|
2066
|
+
* @param query - Search query or verse reference
|
|
2067
|
+
* @returns API response JSON
|
|
2068
|
+
* @throws APIError if request fails
|
|
2069
|
+
*/
|
|
2070
|
+
async makeRequest(query) {
|
|
2071
|
+
const buildId = await this.getBuildId();
|
|
2072
|
+
const url = new URL(`${_LSBibleClient.BASE_URL}/_next/data/${buildId}/index.json`);
|
|
2073
|
+
url.searchParams.set("q", query);
|
|
2074
|
+
try {
|
|
2075
|
+
const controller = new AbortController();
|
|
2076
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
2077
|
+
const response = await fetch(url.toString(), {
|
|
2078
|
+
signal: controller.signal,
|
|
2079
|
+
headers: {
|
|
2080
|
+
...this.headers,
|
|
2081
|
+
referer: `${_LSBibleClient.BASE_URL}/`,
|
|
2082
|
+
"x-nextjs-data": "1"
|
|
2083
|
+
}
|
|
2084
|
+
});
|
|
2085
|
+
clearTimeout(timeoutId);
|
|
2086
|
+
if (!response.ok) {
|
|
2087
|
+
throw new APIError(
|
|
2088
|
+
`API request failed with status ${response.status}: ${response.statusText}`
|
|
2089
|
+
);
|
|
2090
|
+
}
|
|
2091
|
+
return await response.json();
|
|
2092
|
+
} catch (error) {
|
|
2093
|
+
if (error instanceof APIError) {
|
|
2094
|
+
throw error;
|
|
2095
|
+
}
|
|
2096
|
+
throw new APIError(
|
|
2097
|
+
`API request failed: ${error instanceof Error ? error.message : String(error)}`
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Detect if response is from text search or Bible reference lookup.
|
|
2103
|
+
*
|
|
2104
|
+
* Text searches have initialItems array with metadata.
|
|
2105
|
+
* Bible reference lookups have passages array with full HTML.
|
|
2106
|
+
*/
|
|
2107
|
+
isTextSearch(pageProps) {
|
|
2108
|
+
return "initialItems" in pageProps && "totalCount" in pageProps;
|
|
2109
|
+
}
|
|
2110
|
+
/**
|
|
2111
|
+
* Parse text search results from initialItems format.
|
|
2112
|
+
*/
|
|
2113
|
+
parseSearchResults(pageProps, query) {
|
|
2114
|
+
const passages = [];
|
|
2115
|
+
const initialItems = pageProps.initialItems ?? [];
|
|
2116
|
+
for (const item of initialItems) {
|
|
2117
|
+
const key = item.key;
|
|
2118
|
+
const parts = key.split("-");
|
|
2119
|
+
if (parts.length !== 3) continue;
|
|
2120
|
+
const bookNumber = Number.parseInt(parts[0] ?? "0", 10);
|
|
2121
|
+
const chapter = Number.parseInt(parts[1] ?? "0", 10);
|
|
2122
|
+
const verse = Number.parseInt(parts[2] ?? "0", 10);
|
|
2123
|
+
const verseRef = createVerseReference({ bookNumber, chapter, verse });
|
|
2124
|
+
const htmlSnippet = item.html ?? "";
|
|
2125
|
+
const plainText = parseSearchResultHtml(htmlSnippet);
|
|
2126
|
+
const segment = {
|
|
2127
|
+
text: plainText,
|
|
2128
|
+
isRedLetter: false,
|
|
2129
|
+
isItalic: false,
|
|
2130
|
+
isBold: false,
|
|
2131
|
+
isSmallCaps: false
|
|
2132
|
+
};
|
|
2133
|
+
const verseContent = createVerseContent({
|
|
2134
|
+
reference: verseRef,
|
|
2135
|
+
verseNumber: verse,
|
|
2136
|
+
segments: [segment],
|
|
2137
|
+
hasSubheading: false,
|
|
2138
|
+
subheadingText: null,
|
|
2139
|
+
isPoetry: false,
|
|
2140
|
+
isProse: false,
|
|
2141
|
+
chapterStart: false
|
|
2142
|
+
});
|
|
2143
|
+
passages.push(
|
|
2144
|
+
createPassage({
|
|
2145
|
+
fromRef: verseRef,
|
|
2146
|
+
toRef: verseRef,
|
|
2147
|
+
title: verseRef.toString(),
|
|
2148
|
+
verses: [verseContent]
|
|
2149
|
+
})
|
|
2150
|
+
);
|
|
2151
|
+
}
|
|
2152
|
+
const totalCount = pageProps.totalCount ?? 0;
|
|
2153
|
+
const filteredCount = pageProps.filteredCount ?? 0;
|
|
2154
|
+
const countsByBook = pageProps.countsByBook;
|
|
2155
|
+
const countsBySection = pageProps.countsBySection;
|
|
2156
|
+
return createSearchResponse({
|
|
2157
|
+
query,
|
|
2158
|
+
matchCount: totalCount,
|
|
2159
|
+
passages,
|
|
2160
|
+
durationMs: pageProps.duration ?? 0,
|
|
2161
|
+
timestamp: pageProps.start ?? 0,
|
|
2162
|
+
totalCount,
|
|
2163
|
+
filteredCount,
|
|
2164
|
+
countsByBook,
|
|
2165
|
+
countsBySection
|
|
2166
|
+
});
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Parse Bible reference lookup results from passages format.
|
|
2170
|
+
*/
|
|
2171
|
+
parseReferenceResults(pageProps, query) {
|
|
2172
|
+
const passages = [];
|
|
2173
|
+
const passagesData = pageProps.passages ?? [];
|
|
2174
|
+
for (const passageData of passagesData) {
|
|
2175
|
+
const fromData = passageData.from;
|
|
2176
|
+
const toData = passageData.to;
|
|
2177
|
+
const fromRef = createVerseReference({
|
|
2178
|
+
bookNumber: fromData.bn ?? 0,
|
|
2179
|
+
chapter: fromData.cn ?? 0,
|
|
2180
|
+
verse: fromData.vn ?? 0
|
|
2181
|
+
});
|
|
2182
|
+
const toRef = createVerseReference({
|
|
2183
|
+
bookNumber: toData.bn ?? 0,
|
|
2184
|
+
chapter: toData.cn ?? 0,
|
|
2185
|
+
verse: toData.vn ?? 0
|
|
2186
|
+
});
|
|
2187
|
+
const passageHtml = passageData.passageHtml ?? "";
|
|
2188
|
+
const verses = parsePassageHtml(passageHtml);
|
|
2189
|
+
passages.push(
|
|
2190
|
+
createPassage({
|
|
2191
|
+
fromRef,
|
|
2192
|
+
toRef,
|
|
2193
|
+
title: passageData.title ?? "",
|
|
2194
|
+
verses
|
|
2195
|
+
})
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
return createSearchResponse({
|
|
2199
|
+
query,
|
|
2200
|
+
matchCount: pageProps.searchMatchCount ?? 0,
|
|
2201
|
+
passages,
|
|
2202
|
+
durationMs: pageProps.duration ?? 0,
|
|
2203
|
+
timestamp: pageProps.start ?? 0
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
/**
|
|
2207
|
+
* Parse API response into SearchResponse.
|
|
2208
|
+
*/
|
|
2209
|
+
parseResponse(data, query) {
|
|
2210
|
+
const responseData = data;
|
|
2211
|
+
const pageProps = responseData.pageProps ?? {};
|
|
2212
|
+
if (this.isTextSearch(pageProps)) {
|
|
2213
|
+
return this.parseSearchResults(pageProps, query);
|
|
2214
|
+
}
|
|
2215
|
+
return this.parseReferenceResults(pageProps, query);
|
|
2216
|
+
}
|
|
2217
|
+
/**
|
|
2218
|
+
* Search for passages containing text.
|
|
2219
|
+
*
|
|
2220
|
+
* @param query - Search text (e.g., "love", "faith")
|
|
2221
|
+
* @returns SearchResponse with structured passage data
|
|
2222
|
+
* @throws APIError if API request fails
|
|
2223
|
+
*/
|
|
2224
|
+
async search(query) {
|
|
2225
|
+
return this.withCache(`search:${query}`, this.cacheTtls.search, async () => {
|
|
2226
|
+
const data = await this.makeRequest(query);
|
|
2227
|
+
return this.parseResponse(data, query);
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
/**
|
|
2231
|
+
* Get a specific verse with validated parameters.
|
|
2232
|
+
*
|
|
2233
|
+
* @param book - Book name as enum or string
|
|
2234
|
+
* @param chapter - Chapter number (validated against book)
|
|
2235
|
+
* @param verse - Verse number (validated against chapter)
|
|
2236
|
+
* @returns Single Passage containing the verse
|
|
2237
|
+
* @throws InvalidReferenceError if book/chapter/verse combination is invalid
|
|
2238
|
+
* @throws APIError if API request fails
|
|
2239
|
+
*
|
|
2240
|
+
* @example
|
|
2241
|
+
* ```ts
|
|
2242
|
+
* // Using enum (recommended - type-safe with autocomplete)
|
|
2243
|
+
* const passage = await client.getVerse(BookName.JOHN, 3, 16);
|
|
2244
|
+
*
|
|
2245
|
+
* // Using string (validated at runtime)
|
|
2246
|
+
* const passage2 = await client.getVerse("John", 3, 16);
|
|
2247
|
+
* ```
|
|
2248
|
+
*/
|
|
2249
|
+
async getVerse(book, chapter, verse) {
|
|
2250
|
+
validateReference(book, chapter, verse);
|
|
2251
|
+
const bookName = normalizeBookName(book);
|
|
2252
|
+
const query = `${bookName} ${chapter}:${verse}`;
|
|
2253
|
+
return this.withCache(`verse:${query}`, this.cacheTtls.verse, async () => {
|
|
2254
|
+
const response = await this.search(query);
|
|
2255
|
+
if (response.passages.length === 0) {
|
|
2256
|
+
throw new APIError(`No passage found for ${query}`);
|
|
2257
|
+
}
|
|
2258
|
+
const passage = response.passages[0];
|
|
2259
|
+
if (!passage) {
|
|
2260
|
+
throw new APIError(`No passage found for ${query}`);
|
|
2261
|
+
}
|
|
2262
|
+
return passage;
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
/**
|
|
2266
|
+
* Get a passage spanning multiple verses.
|
|
2267
|
+
*
|
|
2268
|
+
* @param fromBook - Starting book
|
|
2269
|
+
* @param fromChapter - Starting chapter
|
|
2270
|
+
* @param fromVerse - Starting verse
|
|
2271
|
+
* @param toBook - Ending book
|
|
2272
|
+
* @param toChapter - Ending chapter
|
|
2273
|
+
* @param toVerse - Ending verse
|
|
2274
|
+
* @returns Passage containing all verses in range
|
|
2275
|
+
* @throws InvalidReferenceError if any reference is invalid
|
|
2276
|
+
* @throws APIError if API request fails
|
|
2277
|
+
*
|
|
2278
|
+
* @example
|
|
2279
|
+
* ```ts
|
|
2280
|
+
* // Get John 3:16-18
|
|
2281
|
+
* const passage = await client.getPassage(
|
|
2282
|
+
* BookName.JOHN, 3, 16,
|
|
2283
|
+
* BookName.JOHN, 3, 18
|
|
2284
|
+
* );
|
|
2285
|
+
* ```
|
|
2286
|
+
*/
|
|
2287
|
+
async getPassage(fromBook, fromChapter, fromVerse, toBook, toChapter, toVerse) {
|
|
2288
|
+
const fromRef = validateReference(fromBook, fromChapter, fromVerse);
|
|
2289
|
+
const toRef = validateReference(toBook, toChapter, toVerse);
|
|
2290
|
+
const fromBookName = normalizeBookName(fromBook);
|
|
2291
|
+
const toBookName = normalizeBookName(toBook);
|
|
2292
|
+
let query;
|
|
2293
|
+
if (fromRef.bookNumber === toRef.bookNumber) {
|
|
2294
|
+
if (fromChapter === toChapter) {
|
|
2295
|
+
query = `${fromBookName} ${fromChapter}:${fromVerse}-${toVerse}`;
|
|
2296
|
+
} else {
|
|
2297
|
+
query = `${fromBookName} ${fromChapter}:${fromVerse}-${toChapter}:${toVerse}`;
|
|
2298
|
+
}
|
|
2299
|
+
} else {
|
|
2300
|
+
query = `${fromBookName} ${fromChapter}:${fromVerse}-${toBookName} ${toChapter}:${toVerse}`;
|
|
2301
|
+
}
|
|
2302
|
+
return this.withCache(`passage:${query}`, this.cacheTtls.passage, async () => {
|
|
2303
|
+
const response = await this.search(query);
|
|
2304
|
+
if (response.passages.length === 0) {
|
|
2305
|
+
throw new APIError(`No passage found for ${query}`);
|
|
2306
|
+
}
|
|
2307
|
+
const passage = response.passages[0];
|
|
2308
|
+
if (!passage) {
|
|
2309
|
+
throw new APIError(`No passage found for ${query}`);
|
|
2310
|
+
}
|
|
2311
|
+
return passage;
|
|
2312
|
+
});
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* Get an entire chapter.
|
|
2316
|
+
*
|
|
2317
|
+
* @param book - Book name
|
|
2318
|
+
* @param chapter - Chapter number
|
|
2319
|
+
* @returns Passage containing all verses in the chapter
|
|
2320
|
+
* @throws InvalidReferenceError if book/chapter is invalid
|
|
2321
|
+
* @throws APIError if API request fails
|
|
2322
|
+
*
|
|
2323
|
+
* @example
|
|
2324
|
+
* ```ts
|
|
2325
|
+
* // Get all of John chapter 3
|
|
2326
|
+
* const passage = await client.getChapter(BookName.JOHN, 3);
|
|
2327
|
+
* ```
|
|
2328
|
+
*/
|
|
2329
|
+
async getChapter(book, chapter) {
|
|
2330
|
+
const bookNumber = getBookNumber(book);
|
|
2331
|
+
const bookInfo = BIBLE_STRUCTURE[bookNumber];
|
|
2332
|
+
if (!bookInfo) {
|
|
2333
|
+
throw new APIError(`Invalid book number: ${bookNumber}`);
|
|
2334
|
+
}
|
|
2335
|
+
const maxChapter = bookInfo.chapters;
|
|
2336
|
+
if (chapter < 1 || chapter > maxChapter) {
|
|
2337
|
+
const bookName2 = normalizeBookName(book);
|
|
2338
|
+
throw new APIError(
|
|
2339
|
+
`${bookName2} only has ${maxChapter} chapters, but chapter ${chapter} was requested`
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
2342
|
+
const bookName = normalizeBookName(book);
|
|
2343
|
+
const query = `${bookName} ${chapter}`;
|
|
2344
|
+
return this.withCache(`chapter:${query}`, this.cacheTtls.chapter, async () => {
|
|
2345
|
+
const response = await this.search(query);
|
|
2346
|
+
if (response.passages.length === 0) {
|
|
2347
|
+
throw new APIError(`No passage found for ${query}`);
|
|
2348
|
+
}
|
|
2349
|
+
const passage = response.passages[0];
|
|
2350
|
+
if (!passage) {
|
|
2351
|
+
throw new APIError(`No passage found for ${query}`);
|
|
2352
|
+
}
|
|
2353
|
+
return passage;
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2356
|
+
/**
|
|
2357
|
+
* Clear all cached data.
|
|
2358
|
+
*
|
|
2359
|
+
* This method calls the cache provider's clear method if one is configured.
|
|
2360
|
+
* If the cache provider doesn't implement a clear method, this is a no-op.
|
|
2361
|
+
*
|
|
2362
|
+
* @example
|
|
2363
|
+
* ```ts
|
|
2364
|
+
* const client = new LSBibleClient({
|
|
2365
|
+
* cache: { provider: new MemoryCacheProvider() }
|
|
2366
|
+
* });
|
|
2367
|
+
*
|
|
2368
|
+
* // Clear all cached data
|
|
2369
|
+
* client.clearCache();
|
|
2370
|
+
* ```
|
|
2371
|
+
*/
|
|
2372
|
+
clearCache() {
|
|
2373
|
+
if (this.cacheProvider && "clear" in this.cacheProvider) {
|
|
2374
|
+
this.cacheProvider.clear();
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
|
|
2379
|
+
// src/mcp/tools.ts
|
|
2380
|
+
function registerTools(server, client) {
|
|
2381
|
+
const apiClient = client ?? new LSBibleClient({
|
|
2382
|
+
cache: {
|
|
2383
|
+
provider: new MemoryCacheProvider()
|
|
2384
|
+
}
|
|
2385
|
+
});
|
|
2386
|
+
server.registerTool(
|
|
2387
|
+
"get_verse",
|
|
2388
|
+
{
|
|
2389
|
+
title: "Get Bible Verse",
|
|
2390
|
+
description: "Fetch a single Bible verse by book, chapter, and verse",
|
|
2391
|
+
inputSchema: {
|
|
2392
|
+
book: zod.z.nativeEnum(BookName).describe("Book name (e.g., John, Genesis)"),
|
|
2393
|
+
chapter: zod.z.number().int().positive().describe("Chapter number"),
|
|
2394
|
+
verse: zod.z.number().int().positive().describe("Verse number")
|
|
2395
|
+
},
|
|
2396
|
+
outputSchema: {
|
|
2397
|
+
reference: zod.z.object({
|
|
2398
|
+
book: zod.z.string(),
|
|
2399
|
+
chapter: zod.z.number(),
|
|
2400
|
+
verse: zod.z.number()
|
|
2401
|
+
}),
|
|
2402
|
+
text: zod.z.string(),
|
|
2403
|
+
segments: zod.z.array(
|
|
2404
|
+
zod.z.object({
|
|
2405
|
+
text: zod.z.string(),
|
|
2406
|
+
isRedLetter: zod.z.boolean().optional(),
|
|
2407
|
+
isItalic: zod.z.boolean().optional(),
|
|
2408
|
+
isSmallCaps: zod.z.boolean().optional(),
|
|
2409
|
+
isBold: zod.z.boolean().optional()
|
|
2410
|
+
})
|
|
2411
|
+
)
|
|
2412
|
+
}
|
|
2413
|
+
},
|
|
2414
|
+
async ({ book, chapter, verse }) => {
|
|
2415
|
+
try {
|
|
2416
|
+
const passage = await apiClient.getVerse(book, chapter, verse);
|
|
2417
|
+
const verseData = passage.verses[0];
|
|
2418
|
+
if (!verseData) {
|
|
2419
|
+
const output2 = {
|
|
2420
|
+
error: `No verse found for ${book} ${chapter}:${verse}`
|
|
2421
|
+
};
|
|
2422
|
+
return {
|
|
2423
|
+
content: [{ type: "text", text: JSON.stringify(output2) }],
|
|
2424
|
+
isError: true
|
|
2425
|
+
};
|
|
2426
|
+
}
|
|
2427
|
+
const output = {
|
|
2428
|
+
reference: {
|
|
2429
|
+
book: verseData.reference.bookName,
|
|
2430
|
+
chapter: verseData.reference.chapter,
|
|
2431
|
+
verse: verseData.reference.verse
|
|
2432
|
+
},
|
|
2433
|
+
text: verseData.plainText,
|
|
2434
|
+
segments: verseData.segments
|
|
2435
|
+
};
|
|
2436
|
+
return {
|
|
2437
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
2438
|
+
structuredContent: output
|
|
2439
|
+
};
|
|
2440
|
+
} catch (error) {
|
|
2441
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2442
|
+
return {
|
|
2443
|
+
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
2444
|
+
isError: true
|
|
2445
|
+
};
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
);
|
|
2449
|
+
server.registerTool(
|
|
2450
|
+
"get_passage",
|
|
2451
|
+
{
|
|
2452
|
+
title: "Get Bible Passage",
|
|
2453
|
+
description: "Fetch a range of verses (single or multi-chapter)",
|
|
2454
|
+
inputSchema: {
|
|
2455
|
+
fromBook: zod.z.nativeEnum(BookName).describe("Starting book"),
|
|
2456
|
+
fromChapter: zod.z.number().int().positive().describe("Starting chapter"),
|
|
2457
|
+
fromVerse: zod.z.number().int().positive().describe("Starting verse"),
|
|
2458
|
+
toBook: zod.z.nativeEnum(BookName).describe("Ending book"),
|
|
2459
|
+
toChapter: zod.z.number().int().positive().describe("Ending chapter"),
|
|
2460
|
+
toVerse: zod.z.number().int().positive().describe("Ending verse")
|
|
2461
|
+
},
|
|
2462
|
+
outputSchema: {
|
|
2463
|
+
reference: zod.z.object({
|
|
2464
|
+
from: zod.z.object({
|
|
2465
|
+
book: zod.z.string(),
|
|
2466
|
+
chapter: zod.z.number(),
|
|
2467
|
+
verse: zod.z.number()
|
|
2468
|
+
}),
|
|
2469
|
+
to: zod.z.object({
|
|
2470
|
+
book: zod.z.string(),
|
|
2471
|
+
chapter: zod.z.number(),
|
|
2472
|
+
verse: zod.z.number()
|
|
2473
|
+
})
|
|
2474
|
+
}),
|
|
2475
|
+
verses: zod.z.array(
|
|
2476
|
+
zod.z.object({
|
|
2477
|
+
reference: zod.z.object({
|
|
2478
|
+
book: zod.z.string(),
|
|
2479
|
+
chapter: zod.z.number(),
|
|
2480
|
+
verse: zod.z.number()
|
|
2481
|
+
}),
|
|
2482
|
+
text: zod.z.string(),
|
|
2483
|
+
segments: zod.z.array(
|
|
2484
|
+
zod.z.object({
|
|
2485
|
+
text: zod.z.string(),
|
|
2486
|
+
isRedLetter: zod.z.boolean().optional(),
|
|
2487
|
+
isItalic: zod.z.boolean().optional(),
|
|
2488
|
+
isSmallCaps: zod.z.boolean().optional(),
|
|
2489
|
+
isBold: zod.z.boolean().optional()
|
|
2490
|
+
})
|
|
2491
|
+
)
|
|
2492
|
+
})
|
|
2493
|
+
)
|
|
2494
|
+
}
|
|
2495
|
+
},
|
|
2496
|
+
async ({ fromBook, fromChapter, fromVerse, toBook, toChapter, toVerse }) => {
|
|
2497
|
+
try {
|
|
2498
|
+
const passage = await apiClient.getPassage(
|
|
2499
|
+
fromBook,
|
|
2500
|
+
fromChapter,
|
|
2501
|
+
fromVerse,
|
|
2502
|
+
toBook,
|
|
2503
|
+
toChapter,
|
|
2504
|
+
toVerse
|
|
2505
|
+
);
|
|
2506
|
+
const output = {
|
|
2507
|
+
reference: {
|
|
2508
|
+
from: {
|
|
2509
|
+
book: passage.fromRef.bookName,
|
|
2510
|
+
chapter: passage.fromRef.chapter,
|
|
2511
|
+
verse: passage.fromRef.verse
|
|
2512
|
+
},
|
|
2513
|
+
to: {
|
|
2514
|
+
book: passage.toRef.bookName,
|
|
2515
|
+
chapter: passage.toRef.chapter,
|
|
2516
|
+
verse: passage.toRef.verse
|
|
2517
|
+
}
|
|
2518
|
+
},
|
|
2519
|
+
verses: passage.verses.map((v) => ({
|
|
2520
|
+
reference: {
|
|
2521
|
+
book: v.reference.bookName,
|
|
2522
|
+
chapter: v.reference.chapter,
|
|
2523
|
+
verse: v.reference.verse
|
|
2524
|
+
},
|
|
2525
|
+
text: v.plainText,
|
|
2526
|
+
segments: v.segments
|
|
2527
|
+
}))
|
|
2528
|
+
};
|
|
2529
|
+
return {
|
|
2530
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
2531
|
+
structuredContent: output
|
|
2532
|
+
};
|
|
2533
|
+
} catch (error) {
|
|
2534
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2535
|
+
return {
|
|
2536
|
+
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
2537
|
+
isError: true
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
);
|
|
2542
|
+
server.registerTool(
|
|
2543
|
+
"get_chapter",
|
|
2544
|
+
{
|
|
2545
|
+
title: "Get Bible Chapter",
|
|
2546
|
+
description: "Fetch an entire chapter",
|
|
2547
|
+
inputSchema: {
|
|
2548
|
+
book: zod.z.nativeEnum(BookName).describe("Book name"),
|
|
2549
|
+
chapter: zod.z.number().int().positive().describe("Chapter number")
|
|
2550
|
+
},
|
|
2551
|
+
outputSchema: {
|
|
2552
|
+
reference: zod.z.object({
|
|
2553
|
+
book: zod.z.string(),
|
|
2554
|
+
chapter: zod.z.number(),
|
|
2555
|
+
verseCount: zod.z.number()
|
|
2556
|
+
}),
|
|
2557
|
+
verses: zod.z.array(
|
|
2558
|
+
zod.z.object({
|
|
2559
|
+
reference: zod.z.object({
|
|
2560
|
+
book: zod.z.string(),
|
|
2561
|
+
chapter: zod.z.number(),
|
|
2562
|
+
verse: zod.z.number()
|
|
2563
|
+
}),
|
|
2564
|
+
text: zod.z.string(),
|
|
2565
|
+
segments: zod.z.array(
|
|
2566
|
+
zod.z.object({
|
|
2567
|
+
text: zod.z.string(),
|
|
2568
|
+
isRedLetter: zod.z.boolean().optional(),
|
|
2569
|
+
isItalic: zod.z.boolean().optional(),
|
|
2570
|
+
isSmallCaps: zod.z.boolean().optional(),
|
|
2571
|
+
isBold: zod.z.boolean().optional()
|
|
2572
|
+
})
|
|
2573
|
+
)
|
|
2574
|
+
})
|
|
2575
|
+
)
|
|
2576
|
+
}
|
|
2577
|
+
},
|
|
2578
|
+
async ({ book, chapter }) => {
|
|
2579
|
+
try {
|
|
2580
|
+
const passage = await apiClient.getChapter(book, chapter);
|
|
2581
|
+
const output = {
|
|
2582
|
+
reference: {
|
|
2583
|
+
book: passage.verses[0]?.reference.bookName ?? book,
|
|
2584
|
+
chapter,
|
|
2585
|
+
verseCount: passage.verses.length
|
|
2586
|
+
},
|
|
2587
|
+
verses: passage.verses.map((v) => ({
|
|
2588
|
+
reference: {
|
|
2589
|
+
book: v.reference.bookName,
|
|
2590
|
+
chapter: v.reference.chapter,
|
|
2591
|
+
verse: v.reference.verse
|
|
2592
|
+
},
|
|
2593
|
+
text: v.plainText,
|
|
2594
|
+
segments: v.segments
|
|
2595
|
+
}))
|
|
2596
|
+
};
|
|
2597
|
+
return {
|
|
2598
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
2599
|
+
structuredContent: output
|
|
2600
|
+
};
|
|
2601
|
+
} catch (error) {
|
|
2602
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2603
|
+
return {
|
|
2604
|
+
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
2605
|
+
isError: true
|
|
2606
|
+
};
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
);
|
|
2610
|
+
server.registerTool(
|
|
2611
|
+
"search_bible",
|
|
2612
|
+
{
|
|
2613
|
+
title: "Search Bible",
|
|
2614
|
+
description: "Full-text search across the entire Bible",
|
|
2615
|
+
inputSchema: {
|
|
2616
|
+
query: zod.z.string().describe("Search query text"),
|
|
2617
|
+
includeDistribution: zod.z.boolean().optional().default(false).describe("Include search result distribution by section and book")
|
|
2618
|
+
},
|
|
2619
|
+
outputSchema: {
|
|
2620
|
+
query: zod.z.string(),
|
|
2621
|
+
resultCount: zod.z.number(),
|
|
2622
|
+
results: zod.z.array(
|
|
2623
|
+
zod.z.object({
|
|
2624
|
+
reference: zod.z.object({
|
|
2625
|
+
book: zod.z.string(),
|
|
2626
|
+
chapter: zod.z.number(),
|
|
2627
|
+
verse: zod.z.number()
|
|
2628
|
+
}),
|
|
2629
|
+
text: zod.z.string(),
|
|
2630
|
+
segments: zod.z.array(
|
|
2631
|
+
zod.z.object({
|
|
2632
|
+
text: zod.z.string(),
|
|
2633
|
+
isRedLetter: zod.z.boolean().optional(),
|
|
2634
|
+
isItalic: zod.z.boolean().optional(),
|
|
2635
|
+
isSmallCaps: zod.z.boolean().optional(),
|
|
2636
|
+
isBold: zod.z.boolean().optional()
|
|
2637
|
+
})
|
|
2638
|
+
)
|
|
2639
|
+
})
|
|
2640
|
+
),
|
|
2641
|
+
distribution: zod.z.object({
|
|
2642
|
+
bySection: zod.z.record(zod.z.string(), zod.z.number()),
|
|
2643
|
+
byBook: zod.z.record(zod.z.string(), zod.z.number())
|
|
2644
|
+
}).optional()
|
|
2645
|
+
}
|
|
2646
|
+
},
|
|
2647
|
+
async ({ query, includeDistribution = false }) => {
|
|
2648
|
+
try {
|
|
2649
|
+
const searchResponse = await apiClient.search(query);
|
|
2650
|
+
const distribution = includeDistribution ? {
|
|
2651
|
+
bySection: searchResponse.countsBySection ?? {},
|
|
2652
|
+
byBook: searchResponse.countsByBook ?? {}
|
|
2653
|
+
} : void 0;
|
|
2654
|
+
const results = searchResponse.passages.flatMap(
|
|
2655
|
+
(passage) => passage.verses.map((v) => ({
|
|
2656
|
+
reference: {
|
|
2657
|
+
book: v.reference.bookName,
|
|
2658
|
+
chapter: v.reference.chapter,
|
|
2659
|
+
verse: v.reference.verse
|
|
2660
|
+
},
|
|
2661
|
+
text: v.plainText,
|
|
2662
|
+
segments: v.segments
|
|
2663
|
+
}))
|
|
2664
|
+
);
|
|
2665
|
+
const output = {
|
|
2666
|
+
query,
|
|
2667
|
+
resultCount: searchResponse.matchCount,
|
|
2668
|
+
results,
|
|
2669
|
+
distribution
|
|
2670
|
+
};
|
|
2671
|
+
return {
|
|
2672
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
2673
|
+
structuredContent: output
|
|
2674
|
+
};
|
|
2675
|
+
} catch (error) {
|
|
2676
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2677
|
+
return {
|
|
2678
|
+
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
2679
|
+
isError: true
|
|
2680
|
+
};
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
);
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
// src/mcp/server.ts
|
|
2687
|
+
function createLSBibleMCPServer() {
|
|
2688
|
+
const server = new mcp_js.McpServer({
|
|
2689
|
+
name: "lsbible",
|
|
2690
|
+
version: "0.1.0"
|
|
2691
|
+
});
|
|
2692
|
+
registerTools(server);
|
|
2693
|
+
registerResources(server);
|
|
2694
|
+
registerPrompts(server);
|
|
2695
|
+
return server;
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
// src/cache/noop.ts
|
|
2699
|
+
var NoopCacheProvider = class {
|
|
2700
|
+
async get(_key) {
|
|
2701
|
+
return void 0;
|
|
2702
|
+
}
|
|
2703
|
+
async set(_key, _value, _ttl) {
|
|
2704
|
+
}
|
|
2705
|
+
};
|
|
2706
|
+
|
|
2707
|
+
exports.CacheTTL = CacheTTL;
|
|
2708
|
+
exports.LSBibleClient = LSBibleClient;
|
|
2709
|
+
exports.MemoryCacheProvider = MemoryCacheProvider;
|
|
2710
|
+
exports.NoopCacheProvider = NoopCacheProvider;
|
|
2711
|
+
exports.createLSBibleMCPServer = createLSBibleMCPServer;
|
|
2712
|
+
exports.registerPrompts = registerPrompts;
|
|
2713
|
+
exports.registerResources = registerResources;
|
|
2714
|
+
exports.registerTools = registerTools;
|
|
2715
|
+
//# sourceMappingURL=index.cjs.map
|
|
2716
|
+
//# sourceMappingURL=index.cjs.map
|