Meet Patel commited on
Commit
12c95f8
·
1 Parent(s): 445cb35

Add project analysis document, version history, and enhance README

Browse files

- Introduced PROJECT_ANALYSIS.md for comprehensive project analysis covering architecture, implementation, and product features.
- Updated README.md with version history, current and upcoming release details, required API keys, and installation instructions.
- Improved installation instructions to include PowerShell examples and clarified server running commands.
- Enhanced tool and resource descriptions in README.md for better clarity on functionalities.
- Refactored run.py to correct directory path for mcp_server and updated server run command.

Files changed (4) hide show
  1. .vscode/PythonImportHelper-v2-Completion.json +0 -2111
  2. PROJECT_ANALYSIS.md +289 -0
  3. README.md +148 -54
  4. run.py +64 -35
.vscode/PythonImportHelper-v2-Completion.json DELETED
@@ -1,2111 +0,0 @@
1
- [
2
- {
3
- "label": "runpy",
4
- "kind": 6,
5
- "isExtraImport": true,
6
- "importPath": "runpy",
7
- "description": "runpy",
8
- "detail": "runpy",
9
- "documentation": {}
10
- },
11
- {
12
- "label": "annotations",
13
- "importPath": "__future__",
14
- "description": "__future__",
15
- "isExtraImport": true,
16
- "detail": "__future__",
17
- "documentation": {}
18
- },
19
- {
20
- "label": "os",
21
- "kind": 6,
22
- "isExtraImport": true,
23
- "importPath": "os",
24
- "description": "os",
25
- "detail": "os",
26
- "documentation": {}
27
- },
28
- {
29
- "label": "site",
30
- "kind": 6,
31
- "isExtraImport": true,
32
- "importPath": "site",
33
- "description": "site",
34
- "detail": "site",
35
- "documentation": {}
36
- },
37
- {
38
- "label": "sys",
39
- "kind": 6,
40
- "isExtraImport": true,
41
- "importPath": "sys",
42
- "description": "sys",
43
- "detail": "sys",
44
- "documentation": {}
45
- },
46
- {
47
- "label": "zip",
48
- "importPath": "builtins",
49
- "description": "builtins",
50
- "isExtraImport": true,
51
- "detail": "builtins",
52
- "documentation": {}
53
- },
54
- {
55
- "label": "str",
56
- "importPath": "builtins",
57
- "description": "builtins",
58
- "isExtraImport": true,
59
- "detail": "builtins",
60
- "documentation": {}
61
- },
62
- {
63
- "label": "os.path",
64
- "kind": 6,
65
- "isExtraImport": true,
66
- "importPath": "os.path",
67
- "description": "os.path",
68
- "detail": "os.path",
69
- "documentation": {}
70
- },
71
- {
72
- "label": "cElementTree",
73
- "importPath": "xml.etree",
74
- "description": "xml.etree",
75
- "isExtraImport": true,
76
- "detail": "xml.etree",
77
- "documentation": {}
78
- },
79
- {
80
- "label": "pyxnat",
81
- "kind": 6,
82
- "isExtraImport": true,
83
- "importPath": "pyxnat",
84
- "description": "pyxnat",
85
- "detail": "pyxnat",
86
- "documentation": {}
87
- },
88
- {
89
- "label": "google.generativeai",
90
- "kind": 6,
91
- "isExtraImport": true,
92
- "importPath": "google.generativeai",
93
- "description": "google.generativeai",
94
- "detail": "google.generativeai",
95
- "documentation": {}
96
- },
97
- {
98
- "label": "Dict",
99
- "importPath": "typing",
100
- "description": "typing",
101
- "isExtraImport": true,
102
- "detail": "typing",
103
- "documentation": {}
104
- },
105
- {
106
- "label": "Any",
107
- "importPath": "typing",
108
- "description": "typing",
109
- "isExtraImport": true,
110
- "detail": "typing",
111
- "documentation": {}
112
- },
113
- {
114
- "label": "Optional",
115
- "importPath": "typing",
116
- "description": "typing",
117
- "isExtraImport": true,
118
- "detail": "typing",
119
- "documentation": {}
120
- },
121
- {
122
- "label": "List",
123
- "importPath": "typing",
124
- "description": "typing",
125
- "isExtraImport": true,
126
- "detail": "typing",
127
- "documentation": {}
128
- },
129
- {
130
- "label": "Literal",
131
- "importPath": "typing",
132
- "description": "typing",
133
- "isExtraImport": true,
134
- "detail": "typing",
135
- "documentation": {}
136
- },
137
- {
138
- "label": "Union",
139
- "importPath": "typing",
140
- "description": "typing",
141
- "isExtraImport": true,
142
- "detail": "typing",
143
- "documentation": {}
144
- },
145
- {
146
- "label": "TypeVar",
147
- "importPath": "typing",
148
- "description": "typing",
149
- "isExtraImport": true,
150
- "detail": "typing",
151
- "documentation": {}
152
- },
153
- {
154
- "label": "Callable",
155
- "importPath": "typing",
156
- "description": "typing",
157
- "isExtraImport": true,
158
- "detail": "typing",
159
- "documentation": {}
160
- },
161
- {
162
- "label": "Dict",
163
- "importPath": "typing",
164
- "description": "typing",
165
- "isExtraImport": true,
166
- "detail": "typing",
167
- "documentation": {}
168
- },
169
- {
170
- "label": "Any",
171
- "importPath": "typing",
172
- "description": "typing",
173
- "isExtraImport": true,
174
- "detail": "typing",
175
- "documentation": {}
176
- },
177
- {
178
- "label": "Dict",
179
- "importPath": "typing",
180
- "description": "typing",
181
- "isExtraImport": true,
182
- "detail": "typing",
183
- "documentation": {}
184
- },
185
- {
186
- "label": "Any",
187
- "importPath": "typing",
188
- "description": "typing",
189
- "isExtraImport": true,
190
- "detail": "typing",
191
- "documentation": {}
192
- },
193
- {
194
- "label": "Dict",
195
- "importPath": "typing",
196
- "description": "typing",
197
- "isExtraImport": true,
198
- "detail": "typing",
199
- "documentation": {}
200
- },
201
- {
202
- "label": "Any",
203
- "importPath": "typing",
204
- "description": "typing",
205
- "isExtraImport": true,
206
- "detail": "typing",
207
- "documentation": {}
208
- },
209
- {
210
- "label": "Optional",
211
- "importPath": "typing",
212
- "description": "typing",
213
- "isExtraImport": true,
214
- "detail": "typing",
215
- "documentation": {}
216
- },
217
- {
218
- "label": "Dict",
219
- "importPath": "typing",
220
- "description": "typing",
221
- "isExtraImport": true,
222
- "detail": "typing",
223
- "documentation": {}
224
- },
225
- {
226
- "label": "Any",
227
- "importPath": "typing",
228
- "description": "typing",
229
- "isExtraImport": true,
230
- "detail": "typing",
231
- "documentation": {}
232
- },
233
- {
234
- "label": "Optional",
235
- "importPath": "typing",
236
- "description": "typing",
237
- "isExtraImport": true,
238
- "detail": "typing",
239
- "documentation": {}
240
- },
241
- {
242
- "label": "Dict",
243
- "importPath": "typing",
244
- "description": "typing",
245
- "isExtraImport": true,
246
- "detail": "typing",
247
- "documentation": {}
248
- },
249
- {
250
- "label": "Any",
251
- "importPath": "typing",
252
- "description": "typing",
253
- "isExtraImport": true,
254
- "detail": "typing",
255
- "documentation": {}
256
- },
257
- {
258
- "label": "List",
259
- "importPath": "typing",
260
- "description": "typing",
261
- "isExtraImport": true,
262
- "detail": "typing",
263
- "documentation": {}
264
- },
265
- {
266
- "label": "Optional",
267
- "importPath": "typing",
268
- "description": "typing",
269
- "isExtraImport": true,
270
- "detail": "typing",
271
- "documentation": {}
272
- },
273
- {
274
- "label": "Dict",
275
- "importPath": "typing",
276
- "description": "typing",
277
- "isExtraImport": true,
278
- "detail": "typing",
279
- "documentation": {}
280
- },
281
- {
282
- "label": "Any",
283
- "importPath": "typing",
284
- "description": "typing",
285
- "isExtraImport": true,
286
- "detail": "typing",
287
- "documentation": {}
288
- },
289
- {
290
- "label": "List",
291
- "importPath": "typing",
292
- "description": "typing",
293
- "isExtraImport": true,
294
- "detail": "typing",
295
- "documentation": {}
296
- },
297
- {
298
- "label": "Optional",
299
- "importPath": "typing",
300
- "description": "typing",
301
- "isExtraImport": true,
302
- "detail": "typing",
303
- "documentation": {}
304
- },
305
- {
306
- "label": "Dict",
307
- "importPath": "typing",
308
- "description": "typing",
309
- "isExtraImport": true,
310
- "detail": "typing",
311
- "documentation": {}
312
- },
313
- {
314
- "label": "Any",
315
- "importPath": "typing",
316
- "description": "typing",
317
- "isExtraImport": true,
318
- "detail": "typing",
319
- "documentation": {}
320
- },
321
- {
322
- "label": "List",
323
- "importPath": "typing",
324
- "description": "typing",
325
- "isExtraImport": true,
326
- "detail": "typing",
327
- "documentation": {}
328
- },
329
- {
330
- "label": "Dict",
331
- "importPath": "typing",
332
- "description": "typing",
333
- "isExtraImport": true,
334
- "detail": "typing",
335
- "documentation": {}
336
- },
337
- {
338
- "label": "Any",
339
- "importPath": "typing",
340
- "description": "typing",
341
- "isExtraImport": true,
342
- "detail": "typing",
343
- "documentation": {}
344
- },
345
- {
346
- "label": "Optional",
347
- "importPath": "typing",
348
- "description": "typing",
349
- "isExtraImport": true,
350
- "detail": "typing",
351
- "documentation": {}
352
- },
353
- {
354
- "label": "Dict",
355
- "importPath": "typing",
356
- "description": "typing",
357
- "isExtraImport": true,
358
- "detail": "typing",
359
- "documentation": {}
360
- },
361
- {
362
- "label": "Any",
363
- "importPath": "typing",
364
- "description": "typing",
365
- "isExtraImport": true,
366
- "detail": "typing",
367
- "documentation": {}
368
- },
369
- {
370
- "label": "List",
371
- "importPath": "typing",
372
- "description": "typing",
373
- "isExtraImport": true,
374
- "detail": "typing",
375
- "documentation": {}
376
- },
377
- {
378
- "label": "Optional",
379
- "importPath": "typing",
380
- "description": "typing",
381
- "isExtraImport": true,
382
- "detail": "typing",
383
- "documentation": {}
384
- },
385
- {
386
- "label": "wraps",
387
- "importPath": "functools",
388
- "description": "functools",
389
- "isExtraImport": true,
390
- "detail": "functools",
391
- "documentation": {}
392
- },
393
- {
394
- "label": "logging",
395
- "kind": 6,
396
- "isExtraImport": true,
397
- "importPath": "logging",
398
- "description": "logging",
399
- "detail": "logging",
400
- "documentation": {}
401
- },
402
- {
403
- "label": "Path",
404
- "importPath": "pathlib",
405
- "description": "pathlib",
406
- "isExtraImport": true,
407
- "detail": "pathlib",
408
- "documentation": {}
409
- },
410
- {
411
- "label": "Path",
412
- "importPath": "pathlib",
413
- "description": "pathlib",
414
- "isExtraImport": true,
415
- "detail": "pathlib",
416
- "documentation": {}
417
- },
418
- {
419
- "label": "Path",
420
- "importPath": "pathlib",
421
- "description": "pathlib",
422
- "isExtraImport": true,
423
- "detail": "pathlib",
424
- "documentation": {}
425
- },
426
- {
427
- "label": "Path",
428
- "importPath": "pathlib",
429
- "description": "pathlib",
430
- "isExtraImport": true,
431
- "detail": "pathlib",
432
- "documentation": {}
433
- },
434
- {
435
- "label": "Path",
436
- "importPath": "pathlib",
437
- "description": "pathlib",
438
- "isExtraImport": true,
439
- "detail": "pathlib",
440
- "documentation": {}
441
- },
442
- {
443
- "label": "Path",
444
- "importPath": "pathlib",
445
- "description": "pathlib",
446
- "isExtraImport": true,
447
- "detail": "pathlib",
448
- "documentation": {}
449
- },
450
- {
451
- "label": "Path",
452
- "importPath": "pathlib",
453
- "description": "pathlib",
454
- "isExtraImport": true,
455
- "detail": "pathlib",
456
- "documentation": {}
457
- },
458
- {
459
- "label": "Path",
460
- "importPath": "pathlib",
461
- "description": "pathlib",
462
- "isExtraImport": true,
463
- "detail": "pathlib",
464
- "documentation": {}
465
- },
466
- {
467
- "label": "Path",
468
- "importPath": "pathlib",
469
- "description": "pathlib",
470
- "isExtraImport": true,
471
- "detail": "pathlib",
472
- "documentation": {}
473
- },
474
- {
475
- "label": "json",
476
- "kind": 6,
477
- "isExtraImport": true,
478
- "importPath": "json",
479
- "description": "json",
480
- "detail": "json",
481
- "documentation": {}
482
- },
483
- {
484
- "label": "concept_graph",
485
- "importPath": "resources",
486
- "description": "resources",
487
- "isExtraImport": true,
488
- "detail": "resources",
489
- "documentation": {}
490
- },
491
- {
492
- "label": "concept_graph",
493
- "importPath": "resources",
494
- "description": "resources",
495
- "isExtraImport": true,
496
- "detail": "resources",
497
- "documentation": {}
498
- },
499
- {
500
- "label": "curriculum_standards",
501
- "importPath": "resources",
502
- "description": "resources",
503
- "isExtraImport": true,
504
- "detail": "resources",
505
- "documentation": {}
506
- },
507
- {
508
- "label": "mcp",
509
- "importPath": "mcp_server.mcp_instance",
510
- "description": "mcp_server.mcp_instance",
511
- "isExtraImport": true,
512
- "detail": "mcp_server.mcp_instance",
513
- "documentation": {}
514
- },
515
- {
516
- "label": "mcp",
517
- "importPath": "mcp_server.mcp_instance",
518
- "description": "mcp_server.mcp_instance",
519
- "isExtraImport": true,
520
- "detail": "mcp_server.mcp_instance",
521
- "documentation": {}
522
- },
523
- {
524
- "label": "mcp",
525
- "importPath": "mcp_server.mcp_instance",
526
- "description": "mcp_server.mcp_instance",
527
- "isExtraImport": true,
528
- "detail": "mcp_server.mcp_instance",
529
- "documentation": {}
530
- },
531
- {
532
- "label": "mcp",
533
- "importPath": "mcp_server.mcp_instance",
534
- "description": "mcp_server.mcp_instance",
535
- "isExtraImport": true,
536
- "detail": "mcp_server.mcp_instance",
537
- "documentation": {}
538
- },
539
- {
540
- "label": "mcp",
541
- "importPath": "mcp_server.mcp_instance",
542
- "description": "mcp_server.mcp_instance",
543
- "isExtraImport": true,
544
- "detail": "mcp_server.mcp_instance",
545
- "documentation": {}
546
- },
547
- {
548
- "label": "mcp",
549
- "importPath": "mcp_server.mcp_instance",
550
- "description": "mcp_server.mcp_instance",
551
- "isExtraImport": true,
552
- "detail": "mcp_server.mcp_instance",
553
- "documentation": {}
554
- },
555
- {
556
- "label": "mcp",
557
- "importPath": "mcp_server.mcp_instance",
558
- "description": "mcp_server.mcp_instance",
559
- "isExtraImport": true,
560
- "detail": "mcp_server.mcp_instance",
561
- "documentation": {}
562
- },
563
- {
564
- "label": "mcp",
565
- "importPath": "mcp_server.mcp_instance",
566
- "description": "mcp_server.mcp_instance",
567
- "isExtraImport": true,
568
- "detail": "mcp_server.mcp_instance",
569
- "documentation": {}
570
- },
571
- {
572
- "label": "GeminiFlash",
573
- "importPath": "mcp_server.model.gemini_flash",
574
- "description": "mcp_server.model.gemini_flash",
575
- "isExtraImport": true,
576
- "detail": "mcp_server.model.gemini_flash",
577
- "documentation": {}
578
- },
579
- {
580
- "label": "GeminiFlash",
581
- "importPath": "mcp_server.model.gemini_flash",
582
- "description": "mcp_server.model.gemini_flash",
583
- "isExtraImport": true,
584
- "detail": "mcp_server.model.gemini_flash",
585
- "documentation": {}
586
- },
587
- {
588
- "label": "GeminiFlash",
589
- "importPath": "mcp_server.model.gemini_flash",
590
- "description": "mcp_server.model.gemini_flash",
591
- "isExtraImport": true,
592
- "detail": "mcp_server.model.gemini_flash",
593
- "documentation": {}
594
- },
595
- {
596
- "label": "GeminiFlash",
597
- "importPath": "mcp_server.model.gemini_flash",
598
- "description": "mcp_server.model.gemini_flash",
599
- "isExtraImport": true,
600
- "detail": "mcp_server.model.gemini_flash",
601
- "documentation": {}
602
- },
603
- {
604
- "label": "GeminiFlash",
605
- "importPath": "mcp_server.model.gemini_flash",
606
- "description": "mcp_server.model.gemini_flash",
607
- "isExtraImport": true,
608
- "detail": "mcp_server.model.gemini_flash",
609
- "documentation": {}
610
- },
611
- {
612
- "label": "GeminiFlash",
613
- "importPath": "mcp_server.model.gemini_flash",
614
- "description": "mcp_server.model.gemini_flash",
615
- "isExtraImport": true,
616
- "detail": "mcp_server.model.gemini_flash",
617
- "documentation": {}
618
- },
619
- {
620
- "label": "random",
621
- "kind": 6,
622
- "isExtraImport": true,
623
- "importPath": "random",
624
- "description": "random",
625
- "detail": "random",
626
- "documentation": {}
627
- },
628
- {
629
- "label": "datetime",
630
- "importPath": "datetime",
631
- "description": "datetime",
632
- "isExtraImport": true,
633
- "detail": "datetime",
634
- "documentation": {}
635
- },
636
- {
637
- "label": "timezone",
638
- "importPath": "datetime",
639
- "description": "datetime",
640
- "isExtraImport": true,
641
- "detail": "datetime",
642
- "documentation": {}
643
- },
644
- {
645
- "label": "datetime",
646
- "importPath": "datetime",
647
- "description": "datetime",
648
- "isExtraImport": true,
649
- "detail": "datetime",
650
- "documentation": {}
651
- },
652
- {
653
- "label": "timedelta",
654
- "importPath": "datetime",
655
- "description": "datetime",
656
- "isExtraImport": true,
657
- "detail": "datetime",
658
- "documentation": {}
659
- },
660
- {
661
- "label": "datetime",
662
- "importPath": "datetime",
663
- "description": "datetime",
664
- "isExtraImport": true,
665
- "detail": "datetime",
666
- "documentation": {}
667
- },
668
- {
669
- "label": "datetime",
670
- "importPath": "datetime",
671
- "description": "datetime",
672
- "isExtraImport": true,
673
- "detail": "datetime",
674
- "documentation": {}
675
- },
676
- {
677
- "label": "get_concept",
678
- "importPath": "resources.concept_graph",
679
- "description": "resources.concept_graph",
680
- "isExtraImport": true,
681
- "detail": "resources.concept_graph",
682
- "documentation": {}
683
- },
684
- {
685
- "label": "get_all_concepts",
686
- "importPath": "resources.concept_graph",
687
- "description": "resources.concept_graph",
688
- "isExtraImport": true,
689
- "detail": "resources.concept_graph",
690
- "documentation": {}
691
- },
692
- {
693
- "label": "CONCEPT_GRAPH",
694
- "importPath": "resources.concept_graph",
695
- "description": "resources.concept_graph",
696
- "isExtraImport": true,
697
- "detail": "resources.concept_graph",
698
- "documentation": {}
699
- },
700
- {
701
- "label": "re",
702
- "kind": 6,
703
- "isExtraImport": true,
704
- "importPath": "re",
705
- "description": "re",
706
- "detail": "re",
707
- "documentation": {}
708
- },
709
- {
710
- "label": "SequenceMatcher",
711
- "importPath": "difflib",
712
- "description": "difflib",
713
- "isExtraImport": true,
714
- "detail": "difflib",
715
- "documentation": {}
716
- },
717
- {
718
- "label": "base64",
719
- "kind": 6,
720
- "isExtraImport": true,
721
- "importPath": "base64",
722
- "description": "base64",
723
- "detail": "base64",
724
- "documentation": {}
725
- },
726
- {
727
- "label": "io",
728
- "kind": 6,
729
- "isExtraImport": true,
730
- "importPath": "io",
731
- "description": "io",
732
- "detail": "io",
733
- "documentation": {}
734
- },
735
- {
736
- "label": "asyncio",
737
- "kind": 6,
738
- "isExtraImport": true,
739
- "importPath": "asyncio",
740
- "description": "asyncio",
741
- "detail": "asyncio",
742
- "documentation": {}
743
- },
744
- {
745
- "label": "aiohttp",
746
- "kind": 6,
747
- "isExtraImport": true,
748
- "importPath": "aiohttp",
749
- "description": "aiohttp",
750
- "detail": "aiohttp",
751
- "documentation": {}
752
- },
753
- {
754
- "label": "GeminiFlash",
755
- "importPath": "model",
756
- "description": "model",
757
- "isExtraImport": true,
758
- "detail": "model",
759
- "documentation": {}
760
- },
761
- {
762
- "label": "uuid",
763
- "kind": 6,
764
- "isExtraImport": true,
765
- "importPath": "uuid",
766
- "description": "uuid",
767
- "detail": "uuid",
768
- "documentation": {}
769
- },
770
- {
771
- "label": "BlobServiceClient",
772
- "importPath": "azure.storage.blob",
773
- "description": "azure.storage.blob",
774
- "isExtraImport": true,
775
- "detail": "azure.storage.blob",
776
- "documentation": {}
777
- },
778
- {
779
- "label": "ContentSettings",
780
- "importPath": "azure.storage.blob",
781
- "description": "azure.storage.blob",
782
- "isExtraImport": true,
783
- "detail": "azure.storage.blob",
784
- "documentation": {}
785
- },
786
- {
787
- "label": "BlobServiceClient",
788
- "importPath": "azure.storage.blob",
789
- "description": "azure.storage.blob",
790
- "isExtraImport": true,
791
- "detail": "azure.storage.blob",
792
- "documentation": {}
793
- },
794
- {
795
- "label": "ContentSettings",
796
- "importPath": "azure.storage.blob",
797
- "description": "azure.storage.blob",
798
- "isExtraImport": true,
799
- "detail": "azure.storage.blob",
800
- "documentation": {}
801
- },
802
- {
803
- "label": "load_dotenv",
804
- "importPath": "dotenv",
805
- "description": "dotenv",
806
- "isExtraImport": true,
807
- "detail": "dotenv",
808
- "documentation": {}
809
- },
810
- {
811
- "label": "load_dotenv",
812
- "importPath": "dotenv",
813
- "description": "dotenv",
814
- "isExtraImport": true,
815
- "detail": "dotenv",
816
- "documentation": {}
817
- },
818
- {
819
- "label": "FastMCP",
820
- "importPath": "mcp.server.fastmcp",
821
- "description": "mcp.server.fastmcp",
822
- "isExtraImport": true,
823
- "detail": "mcp.server.fastmcp",
824
- "documentation": {}
825
- },
826
- {
827
- "label": "FastMCP",
828
- "importPath": "mcp.server.fastmcp",
829
- "description": "mcp.server.fastmcp",
830
- "isExtraImport": true,
831
- "detail": "mcp.server.fastmcp",
832
- "documentation": {}
833
- },
834
- {
835
- "label": "uvicorn",
836
- "kind": 6,
837
- "isExtraImport": true,
838
- "importPath": "uvicorn",
839
- "description": "uvicorn",
840
- "detail": "uvicorn",
841
- "documentation": {}
842
- },
843
- {
844
- "label": "FastAPI",
845
- "importPath": "fastapi",
846
- "description": "fastapi",
847
- "isExtraImport": true,
848
- "detail": "fastapi",
849
- "documentation": {}
850
- },
851
- {
852
- "label": "HTTPException",
853
- "importPath": "fastapi",
854
- "description": "fastapi",
855
- "isExtraImport": true,
856
- "detail": "fastapi",
857
- "documentation": {}
858
- },
859
- {
860
- "label": "UploadFile",
861
- "importPath": "fastapi",
862
- "description": "fastapi",
863
- "isExtraImport": true,
864
- "detail": "fastapi",
865
- "documentation": {}
866
- },
867
- {
868
- "label": "File",
869
- "importPath": "fastapi",
870
- "description": "fastapi",
871
- "isExtraImport": true,
872
- "detail": "fastapi",
873
- "documentation": {}
874
- },
875
- {
876
- "label": "Form",
877
- "importPath": "fastapi",
878
- "description": "fastapi",
879
- "isExtraImport": true,
880
- "detail": "fastapi",
881
- "documentation": {}
882
- },
883
- {
884
- "label": "CORSMiddleware",
885
- "importPath": "fastapi.middleware.cors",
886
- "description": "fastapi.middleware.cors",
887
- "isExtraImport": true,
888
- "detail": "fastapi.middleware.cors",
889
- "documentation": {}
890
- },
891
- {
892
- "label": "concept_tools",
893
- "importPath": "tools",
894
- "description": "tools",
895
- "isExtraImport": true,
896
- "detail": "tools",
897
- "documentation": {}
898
- },
899
- {
900
- "label": "lesson_tools",
901
- "importPath": "tools",
902
- "description": "tools",
903
- "isExtraImport": true,
904
- "detail": "tools",
905
- "documentation": {}
906
- },
907
- {
908
- "label": "quiz_tools",
909
- "importPath": "tools",
910
- "description": "tools",
911
- "isExtraImport": true,
912
- "detail": "tools",
913
- "documentation": {}
914
- },
915
- {
916
- "label": "interaction_tools",
917
- "importPath": "tools",
918
- "description": "tools",
919
- "isExtraImport": true,
920
- "detail": "tools",
921
- "documentation": {}
922
- },
923
- {
924
- "label": "ocr_tools",
925
- "importPath": "tools",
926
- "description": "tools",
927
- "isExtraImport": true,
928
- "detail": "tools",
929
- "documentation": {}
930
- },
931
- {
932
- "label": "learning_path_tools",
933
- "importPath": "tools",
934
- "description": "tools",
935
- "isExtraImport": true,
936
- "detail": "tools",
937
- "documentation": {}
938
- },
939
- {
940
- "label": "concept_tools",
941
- "importPath": "mcp_server.tools",
942
- "description": "mcp_server.tools",
943
- "isExtraImport": true,
944
- "detail": "mcp_server.tools",
945
- "documentation": {}
946
- },
947
- {
948
- "label": "lesson_tools",
949
- "importPath": "mcp_server.tools",
950
- "description": "mcp_server.tools",
951
- "isExtraImport": true,
952
- "detail": "mcp_server.tools",
953
- "documentation": {}
954
- },
955
- {
956
- "label": "quiz_tools",
957
- "importPath": "mcp_server.tools",
958
- "description": "mcp_server.tools",
959
- "isExtraImport": true,
960
- "detail": "mcp_server.tools",
961
- "documentation": {}
962
- },
963
- {
964
- "label": "interaction_tools",
965
- "importPath": "mcp_server.tools",
966
- "description": "mcp_server.tools",
967
- "isExtraImport": true,
968
- "detail": "mcp_server.tools",
969
- "documentation": {}
970
- },
971
- {
972
- "label": "ocr_tools",
973
- "importPath": "mcp_server.tools",
974
- "description": "mcp_server.tools",
975
- "isExtraImport": true,
976
- "detail": "mcp_server.tools",
977
- "documentation": {}
978
- },
979
- {
980
- "label": "learning_path_tools",
981
- "importPath": "mcp_server.tools",
982
- "description": "mcp_server.tools",
983
- "isExtraImport": true,
984
- "detail": "mcp_server.tools",
985
- "documentation": {}
986
- },
987
- {
988
- "label": "concept_graph_tools",
989
- "importPath": "mcp_server.tools",
990
- "description": "mcp_server.tools",
991
- "isExtraImport": true,
992
- "detail": "mcp_server.tools",
993
- "documentation": {}
994
- },
995
- {
996
- "label": "assess_skill_tool",
997
- "importPath": "tools.concept_tools",
998
- "description": "tools.concept_tools",
999
- "isExtraImport": true,
1000
- "detail": "tools.concept_tools",
1001
- "documentation": {}
1002
- },
1003
- {
1004
- "label": "generate_lesson_tool",
1005
- "importPath": "tools.lesson_tools",
1006
- "description": "tools.lesson_tools",
1007
- "isExtraImport": true,
1008
- "detail": "tools.lesson_tools",
1009
- "documentation": {}
1010
- },
1011
- {
1012
- "label": "generate_quiz_tool",
1013
- "importPath": "tools.quiz_tools",
1014
- "description": "tools.quiz_tools",
1015
- "isExtraImport": true,
1016
- "detail": "tools.quiz_tools",
1017
- "documentation": {}
1018
- },
1019
- {
1020
- "label": "setup",
1021
- "importPath": "setuptools",
1022
- "description": "setuptools",
1023
- "isExtraImport": true,
1024
- "detail": "setuptools",
1025
- "documentation": {}
1026
- },
1027
- {
1028
- "label": "find_packages",
1029
- "importPath": "setuptools",
1030
- "description": "setuptools",
1031
- "isExtraImport": true,
1032
- "detail": "setuptools",
1033
- "documentation": {}
1034
- },
1035
- {
1036
- "label": "unittest",
1037
- "kind": 6,
1038
- "isExtraImport": true,
1039
- "importPath": "unittest",
1040
- "description": "unittest",
1041
- "detail": "unittest",
1042
- "documentation": {}
1043
- },
1044
- {
1045
- "label": "patch",
1046
- "importPath": "unittest.mock",
1047
- "description": "unittest.mock",
1048
- "isExtraImport": true,
1049
- "detail": "unittest.mock",
1050
- "documentation": {}
1051
- },
1052
- {
1053
- "label": "MagicMock",
1054
- "importPath": "unittest.mock",
1055
- "description": "unittest.mock",
1056
- "isExtraImport": true,
1057
- "detail": "unittest.mock",
1058
- "documentation": {}
1059
- },
1060
- {
1061
- "label": "patch",
1062
- "importPath": "unittest.mock",
1063
- "description": "unittest.mock",
1064
- "isExtraImport": true,
1065
- "detail": "unittest.mock",
1066
- "documentation": {}
1067
- },
1068
- {
1069
- "label": "MagicMock",
1070
- "importPath": "unittest.mock",
1071
- "description": "unittest.mock",
1072
- "isExtraImport": true,
1073
- "detail": "unittest.mock",
1074
- "documentation": {}
1075
- },
1076
- {
1077
- "label": "patch",
1078
- "importPath": "unittest.mock",
1079
- "description": "unittest.mock",
1080
- "isExtraImport": true,
1081
- "detail": "unittest.mock",
1082
- "documentation": {}
1083
- },
1084
- {
1085
- "label": "MagicMock",
1086
- "importPath": "unittest.mock",
1087
- "description": "unittest.mock",
1088
- "isExtraImport": true,
1089
- "detail": "unittest.mock",
1090
- "documentation": {}
1091
- },
1092
- {
1093
- "label": "requests",
1094
- "kind": 6,
1095
- "isExtraImport": true,
1096
- "importPath": "requests",
1097
- "description": "requests",
1098
- "detail": "requests",
1099
- "documentation": {}
1100
- },
1101
- {
1102
- "label": "TutorXClient",
1103
- "importPath": "client",
1104
- "description": "client",
1105
- "isExtraImport": true,
1106
- "detail": "client",
1107
- "documentation": {}
1108
- },
1109
- {
1110
- "label": "assess_skill",
1111
- "importPath": "main",
1112
- "description": "main",
1113
- "isExtraImport": true,
1114
- "detail": "main",
1115
- "documentation": {}
1116
- },
1117
- {
1118
- "label": "generate_quiz",
1119
- "importPath": "main",
1120
- "description": "main",
1121
- "isExtraImport": true,
1122
- "detail": "main",
1123
- "documentation": {}
1124
- },
1125
- {
1126
- "label": "get_concept_graph",
1127
- "importPath": "main",
1128
- "description": "main",
1129
- "isExtraImport": true,
1130
- "detail": "main",
1131
- "documentation": {}
1132
- },
1133
- {
1134
- "label": "pytest",
1135
- "kind": 6,
1136
- "isExtraImport": true,
1137
- "importPath": "pytest",
1138
- "description": "pytest",
1139
- "detail": "pytest",
1140
- "documentation": {}
1141
- },
1142
- {
1143
- "label": "ClientSession",
1144
- "importPath": "mcp",
1145
- "description": "mcp",
1146
- "isExtraImport": true,
1147
- "detail": "mcp",
1148
- "documentation": {}
1149
- },
1150
- {
1151
- "label": "ClientSession",
1152
- "importPath": "mcp",
1153
- "description": "mcp",
1154
- "isExtraImport": true,
1155
- "detail": "mcp",
1156
- "documentation": {}
1157
- },
1158
- {
1159
- "label": "sse_client",
1160
- "importPath": "mcp.client.sse",
1161
- "description": "mcp.client.sse",
1162
- "isExtraImport": true,
1163
- "detail": "mcp.client.sse",
1164
- "documentation": {}
1165
- },
1166
- {
1167
- "label": "sse_client",
1168
- "importPath": "mcp.client.sse",
1169
- "description": "mcp.client.sse",
1170
- "isExtraImport": true,
1171
- "detail": "mcp.client.sse",
1172
- "documentation": {}
1173
- },
1174
- {
1175
- "label": "process_text_query",
1176
- "importPath": "utils.multimodal",
1177
- "description": "utils.multimodal",
1178
- "isExtraImport": true,
1179
- "detail": "utils.multimodal",
1180
- "documentation": {}
1181
- },
1182
- {
1183
- "label": "process_voice_input",
1184
- "importPath": "utils.multimodal",
1185
- "description": "utils.multimodal",
1186
- "isExtraImport": true,
1187
- "detail": "utils.multimodal",
1188
- "documentation": {}
1189
- },
1190
- {
1191
- "label": "process_handwriting",
1192
- "importPath": "utils.multimodal",
1193
- "description": "utils.multimodal",
1194
- "isExtraImport": true,
1195
- "detail": "utils.multimodal",
1196
- "documentation": {}
1197
- },
1198
- {
1199
- "label": "generate_question",
1200
- "importPath": "utils.assessment",
1201
- "description": "utils.assessment",
1202
- "isExtraImport": true,
1203
- "detail": "utils.assessment",
1204
- "documentation": {}
1205
- },
1206
- {
1207
- "label": "evaluate_student_answer",
1208
- "importPath": "utils.assessment",
1209
- "description": "utils.assessment",
1210
- "isExtraImport": true,
1211
- "detail": "utils.assessment",
1212
- "documentation": {}
1213
- },
1214
- {
1215
- "label": "gradio",
1216
- "kind": 6,
1217
- "isExtraImport": true,
1218
- "importPath": "gradio",
1219
- "description": "gradio",
1220
- "detail": "gradio",
1221
- "documentation": {}
1222
- },
1223
- {
1224
- "label": "numpy",
1225
- "kind": 6,
1226
- "isExtraImport": true,
1227
- "importPath": "numpy",
1228
- "description": "numpy",
1229
- "detail": "numpy",
1230
- "documentation": {}
1231
- },
1232
- {
1233
- "label": "sseclient",
1234
- "kind": 6,
1235
- "isExtraImport": true,
1236
- "importPath": "sseclient",
1237
- "description": "sseclient",
1238
- "detail": "sseclient",
1239
- "documentation": {}
1240
- },
1241
- {
1242
- "label": "upload_to_azure",
1243
- "importPath": "mcp_server.utils.azure_upload",
1244
- "description": "mcp_server.utils.azure_upload",
1245
- "isExtraImport": true,
1246
- "detail": "mcp_server.utils.azure_upload",
1247
- "documentation": {}
1248
- },
1249
- {
1250
- "label": "api_app",
1251
- "importPath": "mcp_server",
1252
- "description": "mcp_server",
1253
- "isExtraImport": true,
1254
- "detail": "mcp_server",
1255
- "documentation": {}
1256
- },
1257
- {
1258
- "label": "mcp",
1259
- "importPath": "mcp_server",
1260
- "description": "mcp_server",
1261
- "isExtraImport": true,
1262
- "detail": "mcp_server",
1263
- "documentation": {}
1264
- },
1265
- {
1266
- "label": "argparse",
1267
- "kind": 6,
1268
- "isExtraImport": true,
1269
- "importPath": "argparse",
1270
- "description": "argparse",
1271
- "detail": "argparse",
1272
- "documentation": {}
1273
- },
1274
- {
1275
- "label": "socket",
1276
- "kind": 6,
1277
- "isExtraImport": true,
1278
- "importPath": "socket",
1279
- "description": "socket",
1280
- "detail": "socket",
1281
- "documentation": {}
1282
- },
1283
- {
1284
- "label": "bin_dir",
1285
- "kind": 5,
1286
- "importPath": ".venv.Scripts.activate_this",
1287
- "description": ".venv.Scripts.activate_this",
1288
- "peekOfCode": "bin_dir = os.path.dirname(abs_file)\nbase = bin_dir[: -len(\"Scripts\") - 1] # strip away the bin part from the __file__, plus the path separator\n# prepend bin to PATH (this file is inside the bin directory)\nos.environ[\"PATH\"] = os.pathsep.join([bin_dir, *os.environ.get(\"PATH\", \"\").split(os.pathsep)])\nos.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"tutorx-mcp\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"..\\\\Lib\\\\site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))",
1289
- "detail": ".venv.Scripts.activate_this",
1290
- "documentation": {}
1291
- },
1292
- {
1293
- "label": "base",
1294
- "kind": 5,
1295
- "importPath": ".venv.Scripts.activate_this",
1296
- "description": ".venv.Scripts.activate_this",
1297
- "peekOfCode": "base = bin_dir[: -len(\"Scripts\") - 1] # strip away the bin part from the __file__, plus the path separator\n# prepend bin to PATH (this file is inside the bin directory)\nos.environ[\"PATH\"] = os.pathsep.join([bin_dir, *os.environ.get(\"PATH\", \"\").split(os.pathsep)])\nos.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"tutorx-mcp\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"..\\\\Lib\\\\site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path)",
1298
- "detail": ".venv.Scripts.activate_this",
1299
- "documentation": {}
1300
- },
1301
- {
1302
- "label": "os.environ[\"PATH\"]",
1303
- "kind": 5,
1304
- "importPath": ".venv.Scripts.activate_this",
1305
- "description": ".venv.Scripts.activate_this",
1306
- "peekOfCode": "os.environ[\"PATH\"] = os.pathsep.join([bin_dir, *os.environ.get(\"PATH\", \"\").split(os.pathsep)])\nos.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"tutorx-mcp\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"..\\\\Lib\\\\site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix",
1307
- "detail": ".venv.Scripts.activate_this",
1308
- "documentation": {}
1309
- },
1310
- {
1311
- "label": "os.environ[\"VIRTUAL_ENV\"]",
1312
- "kind": 5,
1313
- "importPath": ".venv.Scripts.activate_this",
1314
- "description": ".venv.Scripts.activate_this",
1315
- "peekOfCode": "os.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"tutorx-mcp\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"..\\\\Lib\\\\site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
1316
- "detail": ".venv.Scripts.activate_this",
1317
- "documentation": {}
1318
- },
1319
- {
1320
- "label": "os.environ[\"VIRTUAL_ENV_PROMPT\"]",
1321
- "kind": 5,
1322
- "importPath": ".venv.Scripts.activate_this",
1323
- "description": ".venv.Scripts.activate_this",
1324
- "peekOfCode": "os.environ[\"VIRTUAL_ENV_PROMPT\"] = \"tutorx-mcp\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"..\\\\Lib\\\\site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
1325
- "detail": ".venv.Scripts.activate_this",
1326
- "documentation": {}
1327
- },
1328
- {
1329
- "label": "prev_length",
1330
- "kind": 5,
1331
- "importPath": ".venv.Scripts.activate_this",
1332
- "description": ".venv.Scripts.activate_this",
1333
- "peekOfCode": "prev_length = len(sys.path)\nfor lib in \"..\\\\Lib\\\\site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
1334
- "detail": ".venv.Scripts.activate_this",
1335
- "documentation": {}
1336
- },
1337
- {
1338
- "label": "sys.path[:]",
1339
- "kind": 5,
1340
- "importPath": ".venv.Scripts.activate_this",
1341
- "description": ".venv.Scripts.activate_this",
1342
- "peekOfCode": "sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
1343
- "detail": ".venv.Scripts.activate_this",
1344
- "documentation": {}
1345
- },
1346
- {
1347
- "label": "sys.real_prefix",
1348
- "kind": 5,
1349
- "importPath": ".venv.Scripts.activate_this",
1350
- "description": ".venv.Scripts.activate_this",
1351
- "peekOfCode": "sys.real_prefix = sys.prefix\nsys.prefix = base",
1352
- "detail": ".venv.Scripts.activate_this",
1353
- "documentation": {}
1354
- },
1355
- {
1356
- "label": "sys.prefix",
1357
- "kind": 5,
1358
- "importPath": ".venv.Scripts.activate_this",
1359
- "description": ".venv.Scripts.activate_this",
1360
- "peekOfCode": "sys.prefix = base",
1361
- "detail": ".venv.Scripts.activate_this",
1362
- "documentation": {}
1363
- },
1364
- {
1365
- "label": "cmp",
1366
- "kind": 2,
1367
- "importPath": ".venv.Scripts.sessionmirror",
1368
- "description": ".venv.Scripts.sessionmirror",
1369
- "peekOfCode": "def cmp(a, b):\n return (a > b) - (a < b)\nfrom builtins import zip\nfrom builtins import str\nimport os\nimport os.path as op\nimport sys\nfrom xml.etree import cElementTree as ET\nimport pyxnat\nPROJ_ATTRS = [",
1370
- "detail": ".venv.Scripts.sessionmirror",
1371
- "documentation": {}
1372
- },
1373
- {
1374
- "label": "copy_attrs",
1375
- "kind": 2,
1376
- "importPath": ".venv.Scripts.sessionmirror",
1377
- "description": ".venv.Scripts.sessionmirror",
1378
- "peekOfCode": "def copy_attrs(src_obj, dest_obj, attr_list):\n \"\"\" Copies list of attributes form source to destination\"\"\"\n src_attrs = src_obj.attrs.mget(attr_list)\n src_list = dict(list(zip(attr_list, src_attrs)))\n # NOTE: For some reason need to set te again b/c a bug somewhere sets te\n # to sequence name\n te_key = 'xnat:mrScanData/parameters/te'\n if te_key in src_list:\n src_list[te_key] = src_obj.attrs.get(te_key)\n dest_obj.attrs.mset(src_list)",
1379
- "detail": ".venv.Scripts.sessionmirror",
1380
- "documentation": {}
1381
- },
1382
- {
1383
- "label": "copy_attributes",
1384
- "kind": 2,
1385
- "importPath": ".venv.Scripts.sessionmirror",
1386
- "description": ".venv.Scripts.sessionmirror",
1387
- "peekOfCode": "def copy_attributes(src_obj, dest_obj):\n '''Copy attributes from src to dest'''\n src_type = src_obj.datatype()\n types = {'xnat:projectData': PROJ_ATTRS,\n 'xnat:subjectData': SUBJ_ATTRS,\n 'xnat:mrSessionData': MR_EXP_ATTRS,\n 'xnat:petSessionData': PET_EXP_ATTRS,\n 'xnat:ctSessionData': CT_EXP_ATTRS,\n 'xnat:mrScanData': MR_SCAN_ATTRS,\n 'xnat:petScanData': PET_SCAN_ATTRS,",
1388
- "detail": ".venv.Scripts.sessionmirror",
1389
- "documentation": {}
1390
- },
1391
- {
1392
- "label": "subj_compare",
1393
- "kind": 2,
1394
- "importPath": ".venv.Scripts.sessionmirror",
1395
- "description": ".venv.Scripts.sessionmirror",
1396
- "peekOfCode": "def subj_compare(item1, item2):\n '''Compare sort of items'''\n return cmp(item1.label(), item2.label())\ndef copy_file(src_f, dest_r, cache_d):\n '''\n Copy file from XNAT file source to XNAT resource destination,\n using local cache in between'''\n f_label = src_f.label()\n loc_f = cache_d + '/' + f_label\n # Make subdirectories",
1397
- "detail": ".venv.Scripts.sessionmirror",
1398
- "documentation": {}
1399
- },
1400
- {
1401
- "label": "copy_file",
1402
- "kind": 2,
1403
- "importPath": ".venv.Scripts.sessionmirror",
1404
- "description": ".venv.Scripts.sessionmirror",
1405
- "peekOfCode": "def copy_file(src_f, dest_r, cache_d):\n '''\n Copy file from XNAT file source to XNAT resource destination,\n using local cache in between'''\n f_label = src_f.label()\n loc_f = cache_d + '/' + f_label\n # Make subdirectories\n loc_d = op.dirname(loc_f)\n if not op.exists(loc_d):\n os.makedirs(loc_d)",
1406
- "detail": ".venv.Scripts.sessionmirror",
1407
- "documentation": {}
1408
- },
1409
- {
1410
- "label": "copy_res_zip",
1411
- "kind": 2,
1412
- "importPath": ".venv.Scripts.sessionmirror",
1413
- "description": ".venv.Scripts.sessionmirror",
1414
- "peekOfCode": "def copy_res_zip(src_r, dest_r, cache_d):\n '''\n Copy a resource from XNAT source to XNAT destination using local cache\n in between\n '''\n try:\n # Download zip of resource\n print('INFO:Downloading resource as zip...')\n cache_z = src_r.get(cache_d, extract=False)\n # Upload zip of resource",
1415
- "detail": ".venv.Scripts.sessionmirror",
1416
- "documentation": {}
1417
- },
1418
- {
1419
- "label": "is_empty_resource",
1420
- "kind": 2,
1421
- "importPath": ".venv.Scripts.sessionmirror",
1422
- "description": ".venv.Scripts.sessionmirror",
1423
- "peekOfCode": "def is_empty_resource(_res):\n '''Check if resource contains any files'''\n f_count = 0\n for f_in in _res.files().fetchall('obj'):\n f_count += 1\n break\n return f_count == 0\n# copy_project and copy_subject are untested\n# def copy_project(src_proj, dst_proj, proj_cache_dir):\n# '''Copy XNAT project from source to destination'''",
1424
- "detail": ".venv.Scripts.sessionmirror",
1425
- "documentation": {}
1426
- },
1427
- {
1428
- "label": "copy_session",
1429
- "kind": 2,
1430
- "importPath": ".venv.Scripts.sessionmirror",
1431
- "description": ".venv.Scripts.sessionmirror",
1432
- "peekOfCode": "def copy_session(src_sess, dst_sess, sess_cache_dir):\n '''Copy XNAT session from source to destination'''\n print('INFO:uploading session attributes as xml')\n # Write xml to file\n if not op.exists(sess_cache_dir):\n os.makedirs(sess_cache_dir)\n sess_xml = src_sess.get()\n xml_path = op.join(sess_cache_dir, 'sess.xml')\n write_xml(sess_xml, xml_path)\n sess_type = src_sess.datatype()",
1433
- "detail": ".venv.Scripts.sessionmirror",
1434
- "documentation": {}
1435
- },
1436
- {
1437
- "label": "copy_scan",
1438
- "kind": 2,
1439
- "importPath": ".venv.Scripts.sessionmirror",
1440
- "description": ".venv.Scripts.sessionmirror",
1441
- "peekOfCode": "def copy_scan(src_scan, dst_scan, scan_cache_dir):\n '''Copy scan from source XNAT to destination XNAT'''\n scan_type = src_scan.datatype()\n if scan_type == '':\n scan_type = 'xnat:otherDicomScanData'\n dst_scan.create(scans=scan_type)\n copy_attributes(src_scan, dst_scan)\n # Process each resource of scan\n for src_res in src_scan.resources().fetchall('obj'):\n res_label = src_res.label()",
1442
- "detail": ".venv.Scripts.sessionmirror",
1443
- "documentation": {}
1444
- },
1445
- {
1446
- "label": "copy_res",
1447
- "kind": 2,
1448
- "importPath": ".venv.Scripts.sessionmirror",
1449
- "description": ".venv.Scripts.sessionmirror",
1450
- "peekOfCode": "def copy_res(src_res, dst_res, res_cache_dir, use_zip=False):\n '''Copy resource from source XNAT to destination XNAT'''\n # Create cache dir\n if not op.exists(res_cache_dir):\n os.makedirs(res_cache_dir)\n # Prepare resource and check for empty\n is_empty = False\n print(dst_res._uri)\n if not dst_res.exists():\n dst_res.create()",
1451
- "detail": ".venv.Scripts.sessionmirror",
1452
- "documentation": {}
1453
- },
1454
- {
1455
- "label": "write_xml",
1456
- "kind": 2,
1457
- "importPath": ".venv.Scripts.sessionmirror",
1458
- "description": ".venv.Scripts.sessionmirror",
1459
- "peekOfCode": "def write_xml(xml_str, file_path, clean_tags=True):\n \"\"\"Writing XML.\"\"\"\n root = ET.fromstring(xml_str)\n # We only want the tags and attributes relevant to root, no children\n if clean_tags:\n # Remove ID\n if 'ID' in root.attrib:\n del root.attrib['ID']\n # Remove sharing tags\n tag = '{http://nrg.wustl.edu/xnat}sharing'",
1460
- "detail": ".venv.Scripts.sessionmirror",
1461
- "documentation": {}
1462
- },
1463
- {
1464
- "label": "create_parser",
1465
- "kind": 2,
1466
- "importPath": ".venv.Scripts.sessionmirror",
1467
- "description": ".venv.Scripts.sessionmirror",
1468
- "peekOfCode": "def create_parser():\n import argparse\n \"\"\"Parse commandline arguments.\"\"\"\n arg_parser = argparse.ArgumentParser(\n description='Downloads a given experiment/session from an XNAT instance '\n 'and uploads it to an independent one. Only DICOM resources '\n 'will be imported.',\n formatter_class=argparse.RawTextHelpFormatter)\n arg_parser.add_argument(\n '--h1', '--source_config', dest='source_config',",
1469
- "detail": ".venv.Scripts.sessionmirror",
1470
- "documentation": {}
1471
- },
1472
- {
1473
- "label": "main",
1474
- "kind": 2,
1475
- "importPath": ".venv.Scripts.sessionmirror",
1476
- "description": ".venv.Scripts.sessionmirror",
1477
- "peekOfCode": "def main(args):\n x1 = pyxnat.Interface(config=args.source_config)\n x2 = pyxnat.Interface(config=args.dest_config)\n columns = ['subject_label', 'label']\n e1 = x1.array.experiments(experiment_id=args.experiment_id,\n columns=columns).data[0]\n p = x2.select.project(args.project_id)\n s = p.subject(e1['subject_label'])\n if not s.exists():\n s.create()",
1478
- "detail": ".venv.Scripts.sessionmirror",
1479
- "documentation": {}
1480
- },
1481
- {
1482
- "label": "PROJ_ATTRS",
1483
- "kind": 5,
1484
- "importPath": ".venv.Scripts.sessionmirror",
1485
- "description": ".venv.Scripts.sessionmirror",
1486
- "peekOfCode": "PROJ_ATTRS = [\n 'xnat:projectData/name',\n 'xnat:projectData/description',\n 'xnat:projectData/keywords',\n]\nSUBJ_ATTRS = [\n 'xnat:subjectData/group',\n 'xnat:subjectData/src',\n 'xnat:subjectData/investigator/firstname',\n 'xnat:subjectData/investigator/lastname',",
1487
- "detail": ".venv.Scripts.sessionmirror",
1488
- "documentation": {}
1489
- },
1490
- {
1491
- "label": "SUBJ_ATTRS",
1492
- "kind": 5,
1493
- "importPath": ".venv.Scripts.sessionmirror",
1494
- "description": ".venv.Scripts.sessionmirror",
1495
- "peekOfCode": "SUBJ_ATTRS = [\n 'xnat:subjectData/group',\n 'xnat:subjectData/src',\n 'xnat:subjectData/investigator/firstname',\n 'xnat:subjectData/investigator/lastname',\n 'xnat:subjectData/demographics[@xsi:type=xnat:demographicData]/dob',\n 'xnat:subjectData/demographics[@xsi:type=xnat:demographicData]/yob',\n 'xnat:subjectData/demographics[@xsi:type=xnat:demographicData]/age',\n 'xnat:subjectData/demographics[@xsi:type=xnat:demographicData]/gender',\n 'xnat:subjectData/demographics[@xsi:type=xnat:demographicData]/handedness',",
1496
- "detail": ".venv.Scripts.sessionmirror",
1497
- "documentation": {}
1498
- },
1499
- {
1500
- "label": "MR_EXP_ATTRS",
1501
- "kind": 5,
1502
- "importPath": ".venv.Scripts.sessionmirror",
1503
- "description": ".venv.Scripts.sessionmirror",
1504
- "peekOfCode": "MR_EXP_ATTRS = [\n 'xnat:experimentData/date',\n 'xnat:experimentData/visit_id',\n 'xnat:experimentData/time',\n 'xnat:experimentData/note',\n 'xnat:experimentData/investigator/firstname',\n 'xnat:experimentData/investigator/lastname',\n 'xnat:imageSessionData/scanner/manufacturer',\n 'xnat:imageSessionData/scanner/model',\n 'xnat:imageSessionData/operator',",
1505
- "detail": ".venv.Scripts.sessionmirror",
1506
- "documentation": {}
1507
- },
1508
- {
1509
- "label": "OTHER_DICOM_SCAN_ATTRS",
1510
- "kind": 5,
1511
- "importPath": ".venv.Scripts.sessionmirror",
1512
- "description": ".venv.Scripts.sessionmirror",
1513
- "peekOfCode": "OTHER_DICOM_SCAN_ATTRS = [\n 'xnat:imageScanData/type',\n 'xnat:imageScanData/UID',\n 'xnat:imageScanData/note',\n 'xnat:imageScanData/quality',\n 'xnat:imageScanData/condition',\n 'xnat:imageScanData/series_description',\n 'xnat:imageScanData/documentation',\n 'xnat:imageScanData/frames',\n 'xnat:imageScanData/startTime',",
1514
- "detail": ".venv.Scripts.sessionmirror",
1515
- "documentation": {}
1516
- },
1517
- {
1518
- "label": "MR_SCAN_ATTRS",
1519
- "kind": 5,
1520
- "importPath": ".venv.Scripts.sessionmirror",
1521
- "description": ".venv.Scripts.sessionmirror",
1522
- "peekOfCode": "MR_SCAN_ATTRS = [\n 'xnat:imageScanData/type',\n 'xnat:imageScanData/UID',\n 'xnat:imageScanData/note',\n 'xnat:imageScanData/quality',\n 'xnat:imageScanData/condition',\n 'xnat:imageScanData/series_description',\n 'xnat:imageScanData/documentation',\n 'xnat:imageScanData/frames',\n 'xnat:imageScanData/startTime',",
1523
- "detail": ".venv.Scripts.sessionmirror",
1524
- "documentation": {}
1525
- },
1526
- {
1527
- "label": "SC_SCAN_ATTRS",
1528
- "kind": 5,
1529
- "importPath": ".venv.Scripts.sessionmirror",
1530
- "description": ".venv.Scripts.sessionmirror",
1531
- "peekOfCode": "SC_SCAN_ATTRS = [\n 'xnat:imageScanData/type',\n 'xnat:imageScanData/UID',\n 'xnat:imageScanData/note',\n 'xnat:imageScanData/quality',\n 'xnat:imageScanData/condition',\n 'xnat:imageScanData/series_description',\n 'xnat:imageScanData/documentation',\n 'xnat:imageScanData/frames',\n 'xnat:imageScanData/scanner/manufacturer',",
1532
- "detail": ".venv.Scripts.sessionmirror",
1533
- "documentation": {}
1534
- },
1535
- {
1536
- "label": "PET_EXP_ATTRS",
1537
- "kind": 5,
1538
- "importPath": ".venv.Scripts.sessionmirror",
1539
- "description": ".venv.Scripts.sessionmirror",
1540
- "peekOfCode": "PET_EXP_ATTRS = [\n 'xnat:experimentData/date',\n 'xnat:experimentData/visit_id',\n 'xnat:experimentData/time',\n 'xnat:experimentData/note',\n 'xnat:experimentData/investigator/firstname',\n 'xnat:experimentData/investigator/lastname',\n 'xnat:imageSessionData/scanner/manufacturer',\n 'xnat:imageSessionData/scanner/model',\n 'xnat:imageSessionData/operator',",
1541
- "detail": ".venv.Scripts.sessionmirror",
1542
- "documentation": {}
1543
- },
1544
- {
1545
- "label": "CT_EXP_ATTRS",
1546
- "kind": 5,
1547
- "importPath": ".venv.Scripts.sessionmirror",
1548
- "description": ".venv.Scripts.sessionmirror",
1549
- "peekOfCode": "CT_EXP_ATTRS = [\n 'xnat:experimentData/date',\n 'xnat:experimentData/visit_id',\n 'xnat:experimentData/time',\n 'xnat:experimentData/note',\n 'xnat:experimentData/investigator/firstname',\n 'xnat:experimentData/investigator/lastname',\n 'xnat:imageSessionData/scanner/manufacturer',\n 'xnat:imageSessionData/scanner/model',\n 'xnat:imageSessionData/operator',",
1550
- "detail": ".venv.Scripts.sessionmirror",
1551
- "documentation": {}
1552
- },
1553
- {
1554
- "label": "PET_SCAN_ATTRS",
1555
- "kind": 5,
1556
- "importPath": ".venv.Scripts.sessionmirror",
1557
- "description": ".venv.Scripts.sessionmirror",
1558
- "peekOfCode": "PET_SCAN_ATTRS = [\n 'xnat:imageScanData/type',\n 'xnat:imageScanData/UID',\n 'xnat:imageScanData/note',\n 'xnat:imageScanData/quality',\n 'xnat:imageScanData/condition',\n 'xnat:imageScanData/series_description',\n 'xnat:imageScanData/documentation',\n 'xnat:imageScanData/frames',\n 'xnat:imageScanData/scanner/manufacturer',",
1559
- "detail": ".venv.Scripts.sessionmirror",
1560
- "documentation": {}
1561
- },
1562
- {
1563
- "label": "CT_SCAN_ATTRS",
1564
- "kind": 5,
1565
- "importPath": ".venv.Scripts.sessionmirror",
1566
- "description": ".venv.Scripts.sessionmirror",
1567
- "peekOfCode": "CT_SCAN_ATTRS = [\n 'xnat:imageScanData/type',\n 'xnat:imageScanData/UID',\n 'xnat:imageScanData/note',\n 'xnat:imageScanData/quality',\n 'xnat:imageScanData/condition',\n 'xnat:imageScanData/series_description',\n 'xnat:imageScanData/documentation',\n 'xnat:imageScanData/frames',\n 'xnat:imageScanData/scanner/manufacturer',",
1568
- "detail": ".venv.Scripts.sessionmirror",
1569
- "documentation": {}
1570
- },
1571
- {
1572
- "label": "PROC_ATTRS",
1573
- "kind": 5,
1574
- "importPath": ".venv.Scripts.sessionmirror",
1575
- "description": ".venv.Scripts.sessionmirror",
1576
- "peekOfCode": "PROC_ATTRS = [\n 'proc:genProcData/validation/status',\n 'proc:genProcData/procstatus',\n 'proc:genProcData/proctype',\n 'proc:genProcData/procversion',\n 'proc:genProcData/walltimeused',\n 'proc:genProcData/memused'\n]\ndef copy_attrs(src_obj, dest_obj, attr_list):\n \"\"\" Copies list of attributes form source to destination\"\"\"",
1577
- "detail": ".venv.Scripts.sessionmirror",
1578
- "documentation": {}
1579
- },
1580
- {
1581
- "label": "ModelError",
1582
- "kind": 6,
1583
- "importPath": "mcp_server.model.gemini_flash",
1584
- "description": "mcp_server.model.gemini_flash",
1585
- "peekOfCode": "class ModelError(Exception):\n \"\"\"Custom exception for model-related errors\"\"\"\n pass\ndef fallback_to_15_flash(method: Callable[..., T]) -> Callable[..., T]:\n \"\"\"\n Decorator to automatically fall back to 1.5 if 2.0 fails.\n Only applies when the instance's version is '2.0'.\n \"\"\"\n @wraps(method)\n async def wrapper(self: 'GeminiFlash', *args: Any, **kwargs: Any) -> T:",
1586
- "detail": "mcp_server.model.gemini_flash",
1587
- "documentation": {}
1588
- },
1589
- {
1590
- "label": "GeminiFlash",
1591
- "kind": 6,
1592
- "importPath": "mcp_server.model.gemini_flash",
1593
- "description": "mcp_server.model.gemini_flash",
1594
- "peekOfCode": "class GeminiFlash:\n \"\"\"\n Google Gemini Flash model implementation with automatic fallback from 2.0 to 1.5.\n \"\"\"\n SUPPORTED_VERSIONS = ['2.0', '1.5']\n def __init__(self, version: str = '2.0', api_key: Optional[str] = None, _is_fallback: bool = False):\n \"\"\"\n Initialize the Gemini Flash model.\n Args:\n version: Model version ('2.0' or '1.5')",
1595
- "detail": "mcp_server.model.gemini_flash",
1596
- "documentation": {}
1597
- },
1598
- {
1599
- "label": "fallback_to_15_flash",
1600
- "kind": 2,
1601
- "importPath": "mcp_server.model.gemini_flash",
1602
- "description": "mcp_server.model.gemini_flash",
1603
- "peekOfCode": "def fallback_to_15_flash(method: Callable[..., T]) -> Callable[..., T]:\n \"\"\"\n Decorator to automatically fall back to 1.5 if 2.0 fails.\n Only applies when the instance's version is '2.0'.\n \"\"\"\n @wraps(method)\n async def wrapper(self: 'GeminiFlash', *args: Any, **kwargs: Any) -> T:\n if self.version != '2.0' or not self._should_fallback:\n return await method(self, *args, **kwargs)\n try:",
1604
- "detail": "mcp_server.model.gemini_flash",
1605
- "documentation": {}
1606
- },
1607
- {
1608
- "label": "logger",
1609
- "kind": 5,
1610
- "importPath": "mcp_server.model.gemini_flash",
1611
- "description": "mcp_server.model.gemini_flash",
1612
- "peekOfCode": "logger = logging.getLogger(__name__)\nT = TypeVar('T')\nclass ModelError(Exception):\n \"\"\"Custom exception for model-related errors\"\"\"\n pass\ndef fallback_to_15_flash(method: Callable[..., T]) -> Callable[..., T]:\n \"\"\"\n Decorator to automatically fall back to 1.5 if 2.0 fails.\n Only applies when the instance's version is '2.0'.\n \"\"\"",
1613
- "detail": "mcp_server.model.gemini_flash",
1614
- "documentation": {}
1615
- },
1616
- {
1617
- "label": "T",
1618
- "kind": 5,
1619
- "importPath": "mcp_server.model.gemini_flash",
1620
- "description": "mcp_server.model.gemini_flash",
1621
- "peekOfCode": "T = TypeVar('T')\nclass ModelError(Exception):\n \"\"\"Custom exception for model-related errors\"\"\"\n pass\ndef fallback_to_15_flash(method: Callable[..., T]) -> Callable[..., T]:\n \"\"\"\n Decorator to automatically fall back to 1.5 if 2.0 fails.\n Only applies when the instance's version is '2.0'.\n \"\"\"\n @wraps(method)",
1622
- "detail": "mcp_server.model.gemini_flash",
1623
- "documentation": {}
1624
- },
1625
- {
1626
- "label": "get_concept",
1627
- "kind": 2,
1628
- "importPath": "mcp_server.resources.concept_graph",
1629
- "description": "mcp_server.resources.concept_graph",
1630
- "peekOfCode": "def get_concept(concept_id: str) -> Dict[str, Any]:\n \"\"\"Get a specific concept by ID or return None if not found.\"\"\"\n return CONCEPT_GRAPH.get(concept_id)\ndef get_all_concepts() -> Dict[str, Any]:\n \"\"\"Get all concepts in the graph.\"\"\"\n return {\"concepts\": list(CONCEPT_GRAPH.values())}\ndef get_concept_graph() -> Dict[str, Any]:\n \"\"\"Get the complete concept graph.\"\"\"\n return CONCEPT_GRAPH",
1631
- "detail": "mcp_server.resources.concept_graph",
1632
- "documentation": {}
1633
- },
1634
- {
1635
- "label": "get_all_concepts",
1636
- "kind": 2,
1637
- "importPath": "mcp_server.resources.concept_graph",
1638
- "description": "mcp_server.resources.concept_graph",
1639
- "peekOfCode": "def get_all_concepts() -> Dict[str, Any]:\n \"\"\"Get all concepts in the graph.\"\"\"\n return {\"concepts\": list(CONCEPT_GRAPH.values())}\ndef get_concept_graph() -> Dict[str, Any]:\n \"\"\"Get the complete concept graph.\"\"\"\n return CONCEPT_GRAPH",
1640
- "detail": "mcp_server.resources.concept_graph",
1641
- "documentation": {}
1642
- },
1643
- {
1644
- "label": "get_concept_graph",
1645
- "kind": 2,
1646
- "importPath": "mcp_server.resources.concept_graph",
1647
- "description": "mcp_server.resources.concept_graph",
1648
- "peekOfCode": "def get_concept_graph() -> Dict[str, Any]:\n \"\"\"Get the complete concept graph.\"\"\"\n return CONCEPT_GRAPH",
1649
- "detail": "mcp_server.resources.concept_graph",
1650
- "documentation": {}
1651
- },
1652
- {
1653
- "label": "CONCEPT_GRAPH",
1654
- "kind": 5,
1655
- "importPath": "mcp_server.resources.concept_graph",
1656
- "description": "mcp_server.resources.concept_graph",
1657
- "peekOfCode": "CONCEPT_GRAPH = {\n \"python\": {\n \"id\": \"python\",\n \"name\": \"Python Programming\",\n \"description\": \"Fundamentals of Python programming language\",\n \"prerequisites\": [],\n \"related\": [\"functions\", \"oop\", \"data_structures\"]\n },\n \"functions\": {\n \"id\": \"functions\",",
1658
- "detail": "mcp_server.resources.concept_graph",
1659
- "documentation": {}
1660
- },
1661
- {
1662
- "label": "get_curriculum_standards",
1663
- "kind": 2,
1664
- "importPath": "mcp_server.resources.curriculum_standards",
1665
- "description": "mcp_server.resources.curriculum_standards",
1666
- "peekOfCode": "def get_curriculum_standards(country_code: str = \"us\") -> Dict[str, Any]:\n \"\"\"\n Get curriculum standards for a specific country.\n Args:\n country_code: ISO country code (e.g., 'us', 'uk', 'in', 'sg', 'ca')\n Returns:\n Dictionary containing curriculum standards for the specified country\n \"\"\"\n country_code = country_code.lower()\n if country_code not in CURRICULUM_STANDARDS:",
1667
- "detail": "mcp_server.resources.curriculum_standards",
1668
- "documentation": {}
1669
- },
1670
- {
1671
- "label": "CURRICULUM_STANDARDS",
1672
- "kind": 5,
1673
- "importPath": "mcp_server.resources.curriculum_standards",
1674
- "description": "mcp_server.resources.curriculum_standards",
1675
- "peekOfCode": "CURRICULUM_STANDARDS = {\n \"us\": {\n \"name\": \"Common Core State Standards (US)\",\n \"subjects\": {\n \"math\": {\n \"k-5\": [\"Counting & Cardinality\", \"Operations & Algebraic Thinking\", \"Number & Operations\"],\n \"6-8\": [\"Ratios & Proportional Relationships\", \"The Number System\", \"Expressions & Equations\"],\n \"9-12\": [\"Number & Quantity\", \"Algebra\", \"Functions\", \"Modeling\", \"Geometry\", \"Statistics & Probability\"]\n },\n \"ela\": {",
1676
- "detail": "mcp_server.resources.curriculum_standards",
1677
- "documentation": {}
1678
- },
1679
- {
1680
- "label": "current_dir",
1681
- "kind": 5,
1682
- "importPath": "mcp_server.tools.concept_graph_tools",
1683
- "description": "mcp_server.tools.concept_graph_tools",
1684
- "peekOfCode": "current_dir = Path(__file__).parent\nparent_dir = current_dir.parent.parent\nsys.path.insert(0, str(parent_dir))\nimport sys\nimport os\nfrom pathlib import Path\n# Add the parent directory to the Python path\ncurrent_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))",
1685
- "detail": "mcp_server.tools.concept_graph_tools",
1686
- "documentation": {}
1687
- },
1688
- {
1689
- "label": "parent_dir",
1690
- "kind": 5,
1691
- "importPath": "mcp_server.tools.concept_graph_tools",
1692
- "description": "mcp_server.tools.concept_graph_tools",
1693
- "peekOfCode": "parent_dir = current_dir.parent.parent\nsys.path.insert(0, str(parent_dir))\nimport sys\nimport os\nfrom pathlib import Path\n# Add the parent directory to the Python path\ncurrent_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources",
1694
- "detail": "mcp_server.tools.concept_graph_tools",
1695
- "documentation": {}
1696
- },
1697
- {
1698
- "label": "current_dir",
1699
- "kind": 5,
1700
- "importPath": "mcp_server.tools.concept_graph_tools",
1701
- "description": "mcp_server.tools.concept_graph_tools",
1702
- "peekOfCode": "current_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources\nfrom resources import concept_graph\n# Import MCP\nfrom mcp_server.mcp_instance import mcp\nfrom mcp_server.model.gemini_flash import GeminiFlash\nMODEL = GeminiFlash()\[email protected]()",
1703
- "detail": "mcp_server.tools.concept_graph_tools",
1704
- "documentation": {}
1705
- },
1706
- {
1707
- "label": "parent_dir",
1708
- "kind": 5,
1709
- "importPath": "mcp_server.tools.concept_graph_tools",
1710
- "description": "mcp_server.tools.concept_graph_tools",
1711
- "peekOfCode": "parent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources\nfrom resources import concept_graph\n# Import MCP\nfrom mcp_server.mcp_instance import mcp\nfrom mcp_server.model.gemini_flash import GeminiFlash\nMODEL = GeminiFlash()\[email protected]()\nasync def get_concept_graph_tool(concept_id: Optional[str] = None) -> dict:",
1712
- "detail": "mcp_server.tools.concept_graph_tools",
1713
- "documentation": {}
1714
- },
1715
- {
1716
- "label": "MODEL",
1717
- "kind": 5,
1718
- "importPath": "mcp_server.tools.concept_graph_tools",
1719
- "description": "mcp_server.tools.concept_graph_tools",
1720
- "peekOfCode": "MODEL = GeminiFlash()\[email protected]()\nasync def get_concept_graph_tool(concept_id: Optional[str] = None) -> dict:\n \"\"\"\n Get the complete concept graph or a specific concept, fully LLM-driven.\n For a specific concept, use Gemini to generate a JSON object with explanation, related concepts, prerequisites, and summary.\n For the full graph, use Gemini to generate a JSON object with a list of all concepts and their relationships.\n \"\"\"\n if concept_id:\n prompt = (",
1721
- "detail": "mcp_server.tools.concept_graph_tools",
1722
- "documentation": {}
1723
- },
1724
- {
1725
- "label": "current_dir",
1726
- "kind": 5,
1727
- "importPath": "mcp_server.tools.concept_tools",
1728
- "description": "mcp_server.tools.concept_tools",
1729
- "peekOfCode": "current_dir = Path(__file__).parent\nparent_dir = current_dir.parent.parent\nsys.path.insert(0, str(parent_dir))\nimport sys\nimport os\nfrom pathlib import Path\n# Add the parent directory to the Python path\ncurrent_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))",
1730
- "detail": "mcp_server.tools.concept_tools",
1731
- "documentation": {}
1732
- },
1733
- {
1734
- "label": "parent_dir",
1735
- "kind": 5,
1736
- "importPath": "mcp_server.tools.concept_tools",
1737
- "description": "mcp_server.tools.concept_tools",
1738
- "peekOfCode": "parent_dir = current_dir.parent.parent\nsys.path.insert(0, str(parent_dir))\nimport sys\nimport os\nfrom pathlib import Path\n# Add the parent directory to the Python path\ncurrent_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources",
1739
- "detail": "mcp_server.tools.concept_tools",
1740
- "documentation": {}
1741
- },
1742
- {
1743
- "label": "current_dir",
1744
- "kind": 5,
1745
- "importPath": "mcp_server.tools.concept_tools",
1746
- "description": "mcp_server.tools.concept_tools",
1747
- "peekOfCode": "current_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources\nfrom resources.concept_graph import get_concept, get_all_concepts\n# Import MCP\nfrom mcp_server.mcp_instance import mcp\nfrom mcp_server.model.gemini_flash import GeminiFlash\nMODEL = GeminiFlash()\[email protected]()",
1748
- "detail": "mcp_server.tools.concept_tools",
1749
- "documentation": {}
1750
- },
1751
- {
1752
- "label": "parent_dir",
1753
- "kind": 5,
1754
- "importPath": "mcp_server.tools.concept_tools",
1755
- "description": "mcp_server.tools.concept_tools",
1756
- "peekOfCode": "parent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources\nfrom resources.concept_graph import get_concept, get_all_concepts\n# Import MCP\nfrom mcp_server.mcp_instance import mcp\nfrom mcp_server.model.gemini_flash import GeminiFlash\nMODEL = GeminiFlash()\[email protected]()\nasync def get_concept_tool(concept_id: str = None) -> dict:",
1757
- "detail": "mcp_server.tools.concept_tools",
1758
- "documentation": {}
1759
- },
1760
- {
1761
- "label": "MODEL",
1762
- "kind": 5,
1763
- "importPath": "mcp_server.tools.concept_tools",
1764
- "description": "mcp_server.tools.concept_tools",
1765
- "peekOfCode": "MODEL = GeminiFlash()\[email protected]()\nasync def get_concept_tool(concept_id: str = None) -> dict:\n \"\"\"\n Get a specific concept or all concepts from the knowledge graph, fully LLM-driven.\n If a concept_id is provided, use Gemini to generate a JSON object with explanation, key points, and example.\n \"\"\"\n if not concept_id:\n return {\"error\": \"concept_id is required for LLM-driven mode\"}\n prompt = (",
1766
- "detail": "mcp_server.tools.concept_tools",
1767
- "documentation": {}
1768
- },
1769
- {
1770
- "label": "calculate_similarity",
1771
- "kind": 2,
1772
- "importPath": "mcp_server.tools.interaction_tools",
1773
- "description": "mcp_server.tools.interaction_tools",
1774
- "peekOfCode": "def calculate_similarity(text1: str, text2: str) -> float:\n \"\"\"Calculate the similarity ratio between two texts.\"\"\"\n return 0.0 # No longer used, LLM-driven\[email protected]()\nasync def text_interaction(query: str, student_id: str) -> dict:\n \"\"\"\n Process a text query from a student and provide an educational response, fully LLM-driven.\n Use Gemini to generate a JSON object with a response and suggested actions/resources.\n \"\"\"\n prompt = (",
1775
- "detail": "mcp_server.tools.interaction_tools",
1776
- "documentation": {}
1777
- },
1778
- {
1779
- "label": "MODEL",
1780
- "kind": 5,
1781
- "importPath": "mcp_server.tools.interaction_tools",
1782
- "description": "mcp_server.tools.interaction_tools",
1783
- "peekOfCode": "MODEL = GeminiFlash()\ndef calculate_similarity(text1: str, text2: str) -> float:\n \"\"\"Calculate the similarity ratio between two texts.\"\"\"\n return 0.0 # No longer used, LLM-driven\[email protected]()\nasync def text_interaction(query: str, student_id: str) -> dict:\n \"\"\"\n Process a text query from a student and provide an educational response, fully LLM-driven.\n Use Gemini to generate a JSON object with a response and suggested actions/resources.\n \"\"\"",
1784
- "detail": "mcp_server.tools.interaction_tools",
1785
- "documentation": {}
1786
- },
1787
- {
1788
- "label": "get_prerequisites",
1789
- "kind": 2,
1790
- "importPath": "mcp_server.tools.learning_path_tools",
1791
- "description": "mcp_server.tools.learning_path_tools",
1792
- "peekOfCode": "def get_prerequisites(concept_id: str, visited: Optional[set] = None) -> List[Dict[str, Any]]:\n \"\"\"\n Get all prerequisites for a concept recursively.\n Args:\n concept_id: ID of the concept to get prerequisites for\n visited: Set of already visited concepts to avoid cycles\n Returns:\n List of prerequisite concepts in order\n \"\"\"\n if visited is None:",
1793
- "detail": "mcp_server.tools.learning_path_tools",
1794
- "documentation": {}
1795
- },
1796
- {
1797
- "label": "generate_learning_path",
1798
- "kind": 2,
1799
- "importPath": "mcp_server.tools.learning_path_tools",
1800
- "description": "mcp_server.tools.learning_path_tools",
1801
- "peekOfCode": "def generate_learning_path(concept_ids: List[str], student_level: str = \"beginner\") -> Dict[str, Any]:\n \"\"\"\n Generate a personalized learning path for a student.\n Args:\n concept_ids: List of concept IDs to include in the learning path\n student_level: Student's current level (beginner, intermediate, advanced)\n Returns:\n Dictionary containing the learning path\n \"\"\"\n if not concept_ids:",
1802
- "detail": "mcp_server.tools.learning_path_tools",
1803
- "documentation": {}
1804
- },
1805
- {
1806
- "label": "current_dir",
1807
- "kind": 5,
1808
- "importPath": "mcp_server.tools.learning_path_tools",
1809
- "description": "mcp_server.tools.learning_path_tools",
1810
- "peekOfCode": "current_dir = Path(__file__).parent\nparent_dir = current_dir.parent.parent\nsys.path.insert(0, str(parent_dir))\nimport sys\nimport os\nfrom pathlib import Path\n# Add the parent directory to the Python path\ncurrent_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))",
1811
- "detail": "mcp_server.tools.learning_path_tools",
1812
- "documentation": {}
1813
- },
1814
- {
1815
- "label": "parent_dir",
1816
- "kind": 5,
1817
- "importPath": "mcp_server.tools.learning_path_tools",
1818
- "description": "mcp_server.tools.learning_path_tools",
1819
- "peekOfCode": "parent_dir = current_dir.parent.parent\nsys.path.insert(0, str(parent_dir))\nimport sys\nimport os\nfrom pathlib import Path\n# Add the parent directory to the Python path\ncurrent_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources",
1820
- "detail": "mcp_server.tools.learning_path_tools",
1821
- "documentation": {}
1822
- },
1823
- {
1824
- "label": "current_dir",
1825
- "kind": 5,
1826
- "importPath": "mcp_server.tools.learning_path_tools",
1827
- "description": "mcp_server.tools.learning_path_tools",
1828
- "peekOfCode": "current_dir = Path(__file__).parent\nparent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources\nfrom resources.concept_graph import CONCEPT_GRAPH\n# Import MCP\nfrom mcp_server.mcp_instance import mcp\nfrom mcp_server.model.gemini_flash import GeminiFlash\nMODEL = GeminiFlash()\ndef get_prerequisites(concept_id: str, visited: Optional[set] = None) -> List[Dict[str, Any]]:",
1829
- "detail": "mcp_server.tools.learning_path_tools",
1830
- "documentation": {}
1831
- },
1832
- {
1833
- "label": "parent_dir",
1834
- "kind": 5,
1835
- "importPath": "mcp_server.tools.learning_path_tools",
1836
- "description": "mcp_server.tools.learning_path_tools",
1837
- "peekOfCode": "parent_dir = current_dir.parent\nsys.path.insert(0, str(parent_dir))\n# Import from local resources\nfrom resources.concept_graph import CONCEPT_GRAPH\n# Import MCP\nfrom mcp_server.mcp_instance import mcp\nfrom mcp_server.model.gemini_flash import GeminiFlash\nMODEL = GeminiFlash()\ndef get_prerequisites(concept_id: str, visited: Optional[set] = None) -> List[Dict[str, Any]]:\n \"\"\"",
1838
- "detail": "mcp_server.tools.learning_path_tools",
1839
- "documentation": {}
1840
- },
1841
- {
1842
- "label": "MODEL",
1843
- "kind": 5,
1844
- "importPath": "mcp_server.tools.learning_path_tools",
1845
- "description": "mcp_server.tools.learning_path_tools",
1846
- "peekOfCode": "MODEL = GeminiFlash()\ndef get_prerequisites(concept_id: str, visited: Optional[set] = None) -> List[Dict[str, Any]]:\n \"\"\"\n Get all prerequisites for a concept recursively.\n Args:\n concept_id: ID of the concept to get prerequisites for\n visited: Set of already visited concepts to avoid cycles\n Returns:\n List of prerequisite concepts in order\n \"\"\"",
1847
- "detail": "mcp_server.tools.learning_path_tools",
1848
- "documentation": {}
1849
- },
1850
- {
1851
- "label": "MODEL",
1852
- "kind": 5,
1853
- "importPath": "mcp_server.tools.lesson_tools",
1854
- "description": "mcp_server.tools.lesson_tools",
1855
- "peekOfCode": "MODEL = GeminiFlash()\[email protected]()\nasync def generate_lesson_tool(topic: str, grade_level: int, duration_minutes: int) -> dict:\n \"\"\"\n Generate a lesson plan for the given topic, grade level, and duration, fully LLM-driven.\n Use Gemini to generate a JSON object with objectives, activities, materials, assessment, differentiation, and homework.\n \"\"\"\n prompt = (\n f\"Generate a detailed lesson plan as a JSON object for the topic '{topic}', grade {grade_level}, duration {duration_minutes} minutes. \"\n f\"Include fields: objectives (list), activities (list), materials (list), assessment (dict), differentiation (dict), and homework (dict).\"",
1856
- "detail": "mcp_server.tools.lesson_tools",
1857
- "documentation": {}
1858
- },
1859
- {
1860
- "label": "MODEL",
1861
- "kind": 5,
1862
- "importPath": "mcp_server.tools.ocr_tools",
1863
- "description": "mcp_server.tools.ocr_tools",
1864
- "peekOfCode": "MODEL = GeminiFlash()\nasync def mistral_ocr_request(document_url: str) -> dict:\n \"\"\"\n Send OCR request to Mistral OCR service using document URL.\n Args:\n document_url: URL of the document to process\n Returns:\n OCR response from Mistral\n \"\"\"\n try:",
1865
- "detail": "mcp_server.tools.ocr_tools",
1866
- "documentation": {}
1867
- },
1868
- {
1869
- "label": "result",
1870
- "kind": 5,
1871
- "importPath": "mcp_server.tools.ocr_tools",
1872
- "description": "mcp_server.tools.ocr_tools",
1873
- "peekOfCode": "result = await mistral_document_ocr(\"https://example.com/document.pdf\")\n# For image document \nresult = await mistral_document_ocr(\"https://example.com/image.jpg\")\n\"\"\"",
1874
- "detail": "mcp_server.tools.ocr_tools",
1875
- "documentation": {}
1876
- },
1877
- {
1878
- "label": "result",
1879
- "kind": 5,
1880
- "importPath": "mcp_server.tools.ocr_tools",
1881
- "description": "mcp_server.tools.ocr_tools",
1882
- "peekOfCode": "result = await mistral_document_ocr(\"https://example.com/image.jpg\")\n\"\"\"",
1883
- "detail": "mcp_server.tools.ocr_tools",
1884
- "documentation": {}
1885
- },
1886
- {
1887
- "label": "PROMPT_TEMPLATE",
1888
- "kind": 5,
1889
- "importPath": "mcp_server.tools.quiz_tools",
1890
- "description": "mcp_server.tools.quiz_tools",
1891
- "peekOfCode": "PROMPT_TEMPLATE = (Path(__file__).parent.parent / \"prompts\" / \"quiz_generation.txt\").read_text(encoding=\"utf-8\")\n# Initialize Gemini model\nMODEL = GeminiFlash()\[email protected]()\nasync def generate_quiz_tool(concept: str, difficulty: str = \"medium\") -> dict:\n \"\"\"\n Generate a quiz based on a concept and difficulty using Gemini, fully LLM-driven.\n The JSON should include a list of questions, each with options and the correct answer.\n \"\"\"\n try:",
1892
- "detail": "mcp_server.tools.quiz_tools",
1893
- "documentation": {}
1894
- },
1895
- {
1896
- "label": "MODEL",
1897
- "kind": 5,
1898
- "importPath": "mcp_server.tools.quiz_tools",
1899
- "description": "mcp_server.tools.quiz_tools",
1900
- "peekOfCode": "MODEL = GeminiFlash()\[email protected]()\nasync def generate_quiz_tool(concept: str, difficulty: str = \"medium\") -> dict:\n \"\"\"\n Generate a quiz based on a concept and difficulty using Gemini, fully LLM-driven.\n The JSON should include a list of questions, each with options and the correct answer.\n \"\"\"\n try:\n if not concept or not isinstance(concept, str):\n return {\"error\": \"concept must be a non-empty string\"}",
1901
- "detail": "mcp_server.tools.quiz_tools",
1902
- "documentation": {}
1903
- },
1904
- {
1905
- "label": "upload_to_azure",
1906
- "kind": 2,
1907
- "importPath": "mcp_server.utils.azure_upload",
1908
- "description": "mcp_server.utils.azure_upload",
1909
- "peekOfCode": "def upload_to_azure(file_path: str, content_type: str = None) -> str:\n \"\"\"\n Upload a file to Azure Blob Storage and return the public URL.\n Args:\n file_path: Path to the file to upload.\n content_type: Optional MIME type (e.g., 'application/pdf'). If not provided, guessed from extension.\n Returns:\n The public URL of the uploaded blob.\n \"\"\"\n if not AZURE_CONNECTION_STRING or not AZURE_CONTAINER_NAME:",
1910
- "detail": "mcp_server.utils.azure_upload",
1911
- "documentation": {}
1912
- },
1913
- {
1914
- "label": "AZURE_CONNECTION_STRING",
1915
- "kind": 5,
1916
- "importPath": "mcp_server.utils.azure_upload",
1917
- "description": "mcp_server.utils.azure_upload",
1918
- "peekOfCode": "AZURE_CONNECTION_STRING = os.getenv(\"AZURE_CONNECTION_STRING\")\nAZURE_CONTAINER_NAME = os.getenv(\"AZURE_CONTAINER_NAME\")\ndef upload_to_azure(file_path: str, content_type: str = None) -> str:\n \"\"\"\n Upload a file to Azure Blob Storage and return the public URL.\n Args:\n file_path: Path to the file to upload.\n content_type: Optional MIME type (e.g., 'application/pdf'). If not provided, guessed from extension.\n Returns:\n The public URL of the uploaded blob.",
1919
- "detail": "mcp_server.utils.azure_upload",
1920
- "documentation": {}
1921
- },
1922
- {
1923
- "label": "AZURE_CONTAINER_NAME",
1924
- "kind": 5,
1925
- "importPath": "mcp_server.utils.azure_upload",
1926
- "description": "mcp_server.utils.azure_upload",
1927
- "peekOfCode": "AZURE_CONTAINER_NAME = os.getenv(\"AZURE_CONTAINER_NAME\")\ndef upload_to_azure(file_path: str, content_type: str = None) -> str:\n \"\"\"\n Upload a file to Azure Blob Storage and return the public URL.\n Args:\n file_path: Path to the file to upload.\n content_type: Optional MIME type (e.g., 'application/pdf'). If not provided, guessed from extension.\n Returns:\n The public URL of the uploaded blob.\n \"\"\"",
1928
- "detail": "mcp_server.utils.azure_upload",
1929
- "documentation": {}
1930
- },
1931
- {
1932
- "label": "mcp",
1933
- "kind": 5,
1934
- "importPath": "mcp_server.mcp_instance",
1935
- "description": "mcp_server.mcp_instance",
1936
- "peekOfCode": "mcp = FastMCP(\n \"TutorX\",\n dependencies=[\"mcp[cli]>=1.9.3\"],\n cors_origins=[\"*\"]\n)",
1937
- "detail": "mcp_server.mcp_instance",
1938
- "documentation": {}
1939
- },
1940
- {
1941
- "label": "current_dir",
1942
- "kind": 5,
1943
- "importPath": "mcp_server.server",
1944
- "description": "mcp_server.server",
1945
- "peekOfCode": "current_dir = Path(__file__).parent\nsys.path.insert(0, str(current_dir))\nimport uvicorn\nfrom fastapi import FastAPI, HTTPException, UploadFile, File, Form\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom mcp.server.fastmcp import FastMCP\n# Import all tools to register them with MCP\nfrom tools import (\n concept_tools,\n lesson_tools,",
1946
- "detail": "mcp_server.server",
1947
- "documentation": {}
1948
- },
1949
- {
1950
- "label": "api_app",
1951
- "kind": 5,
1952
- "importPath": "mcp_server.server",
1953
- "description": "mcp_server.server",
1954
- "peekOfCode": "api_app = FastAPI(\n title=\"TutorX MCP Server\",\n description=\"Model Context Protocol server for TutorX educational platform\",\n version=\"1.0.0\"\n)\n# Add CORS middleware\napi_app.add_middleware(\n CORSMiddleware,\n allow_origins=[\"*\"],\n allow_credentials=True,",
1955
- "detail": "mcp_server.server",
1956
- "documentation": {}
1957
- },
1958
- {
1959
- "label": "TestTutorXClient",
1960
- "kind": 6,
1961
- "importPath": "tests.test_client",
1962
- "description": "tests.test_client",
1963
- "peekOfCode": "class TestTutorXClient(unittest.TestCase):\n \"\"\"Test cases for the TutorX MCP client\"\"\"\n def setUp(self):\n \"\"\"Set up test fixtures\"\"\"\n self.client = TutorXClient(\"http://localhost:8000\")\n self.student_id = \"test_student_123\"\n self.concept_id = \"math_algebra_basics\"\n @patch('client.requests.post')\n def test_call_tool(self, mock_post):\n \"\"\"Test _call_tool method\"\"\"",
1964
- "detail": "tests.test_client",
1965
- "documentation": {}
1966
- },
1967
- {
1968
- "label": "TestMCPServer",
1969
- "kind": 6,
1970
- "importPath": "tests.test_mcp_server",
1971
- "description": "tests.test_mcp_server",
1972
- "peekOfCode": "class TestMCPServer(unittest.TestCase):\n \"\"\"Test cases for the TutorX MCP server\"\"\"\n def setUp(self):\n \"\"\"Set up test fixtures\"\"\"\n self.student_id = \"test_student_123\"\n self.concept_id = \"math_algebra_basics\"\n def test_assess_skill(self):\n \"\"\"Test assess_skill tool\"\"\"\n result = assess_skill(self.student_id, self.concept_id)\n # Verify the structure of the result",
1973
- "detail": "tests.test_mcp_server",
1974
- "documentation": {}
1975
- },
1976
- {
1977
- "label": "SERVER_URL",
1978
- "kind": 5,
1979
- "importPath": "tests.test_tools_integration",
1980
- "description": "tests.test_tools_integration",
1981
- "peekOfCode": "SERVER_URL = \"http://localhost:8000/sse\" # Adjust if needed\[email protected]\nasync def test_get_concept_graph_tool():\n async with sse_client(SERVER_URL) as (sse, write):\n async with ClientSession(sse, write) as session:\n await session.initialize()\n result = await session.call_tool(\"get_concept_graph_tool\", {\"concept_id\": \"python\"})\n assert result and \"error\" not in result\[email protected]\nasync def test_generate_quiz_tool():",
1982
- "detail": "tests.test_tools_integration",
1983
- "documentation": {}
1984
- },
1985
- {
1986
- "label": "TestMultimodalUtils",
1987
- "kind": 6,
1988
- "importPath": "tests.test_utils",
1989
- "description": "tests.test_utils",
1990
- "peekOfCode": "class TestMultimodalUtils(unittest.TestCase):\n \"\"\"Test cases for multimodal utility functions\"\"\"\n def test_process_text_query(self):\n \"\"\"Test text query processing\"\"\"\n # Test with a \"solve\" query\n solve_query = \"Please solve this equation: 2x + 3 = 7\"\n result = process_text_query(solve_query)\n self.assertIsInstance(result, dict)\n self.assertEqual(result[\"query\"], solve_query)\n self.assertEqual(result[\"response_type\"], \"math_solution\")",
1991
- "detail": "tests.test_utils",
1992
- "documentation": {}
1993
- },
1994
- {
1995
- "label": "TestAssessmentUtils",
1996
- "kind": 6,
1997
- "importPath": "tests.test_utils",
1998
- "description": "tests.test_utils",
1999
- "peekOfCode": "class TestAssessmentUtils(unittest.TestCase):\n \"\"\"Test cases for assessment utility functions\"\"\"\n def test_generate_question_algebra_basics(self):\n \"\"\"Test question generation for algebra basics\"\"\"\n concept_id = \"math_algebra_basics\"\n difficulty = 2\n question = generate_question(concept_id, difficulty)\n self.assertIsInstance(question, dict)\n self.assertIn(\"id\", question)\n self.assertEqual(question[\"concept_id\"], concept_id)",
2000
- "detail": "tests.test_utils",
2001
- "documentation": {}
2002
- },
2003
- {
2004
- "label": "upload_to_azure",
2005
- "kind": 2,
2006
- "importPath": "utils.azure_upload",
2007
- "description": "utils.azure_upload",
2008
- "peekOfCode": "def upload_to_azure(file_path: str, content_type: str = None) -> str:\n \"\"\"\n Upload a file to Azure Blob Storage and return the public URL.\n Args:\n file_path: Path to the file to upload.\n content_type: Optional MIME type (e.g., 'application/pdf'). If not provided, guessed from extension.\n Returns:\n The public URL of the uploaded blob.\n \"\"\"\n if not AZURE_CONNECTION_STRING or not AZURE_CONTAINER_NAME:",
2009
- "detail": "utils.azure_upload",
2010
- "documentation": {}
2011
- },
2012
- {
2013
- "label": "AZURE_CONNECTION_STRING",
2014
- "kind": 5,
2015
- "importPath": "utils.azure_upload",
2016
- "description": "utils.azure_upload",
2017
- "peekOfCode": "AZURE_CONNECTION_STRING = os.getenv(\"AZURE_CONNECTION_STRING\")\nAZURE_CONTAINER_NAME = os.getenv(\"AZURE_CONTAINER_NAME\")\ndef upload_to_azure(file_path: str, content_type: str = None) -> str:\n \"\"\"\n Upload a file to Azure Blob Storage and return the public URL.\n Args:\n file_path: Path to the file to upload.\n content_type: Optional MIME type (e.g., 'application/pdf'). If not provided, guessed from extension.\n Returns:\n The public URL of the uploaded blob.",
2018
- "detail": "utils.azure_upload",
2019
- "documentation": {}
2020
- },
2021
- {
2022
- "label": "AZURE_CONTAINER_NAME",
2023
- "kind": 5,
2024
- "importPath": "utils.azure_upload",
2025
- "description": "utils.azure_upload",
2026
- "peekOfCode": "AZURE_CONTAINER_NAME = os.getenv(\"AZURE_CONTAINER_NAME\")\ndef upload_to_azure(file_path: str, content_type: str = None) -> str:\n \"\"\"\n Upload a file to Azure Blob Storage and return the public URL.\n Args:\n file_path: Path to the file to upload.\n content_type: Optional MIME type (e.g., 'application/pdf'). If not provided, guessed from extension.\n Returns:\n The public URL of the uploaded blob.\n \"\"\"",
2027
- "detail": "utils.azure_upload",
2028
- "documentation": {}
2029
- },
2030
- {
2031
- "label": "SERVER_URL",
2032
- "kind": 5,
2033
- "importPath": "app",
2034
- "description": "app",
2035
- "peekOfCode": "SERVER_URL = \"http://localhost:8000/sse\" # Ensure this is the SSE endpoint\n# Utility functions\nasync def load_concept_graph(concept_id: str = None):\n \"\"\"\n Load and visualize the concept graph for a given concept ID.\n If no concept_id is provided, returns the first available concept.\n Uses call_resource for concept graph retrieval (not a tool).\n Returns:\n tuple: (figure, concept_details, related_concepts) or (None, error_dict, [])\n \"\"\"",
2036
- "detail": "app",
2037
- "documentation": {}
2038
- },
2039
- {
2040
- "label": "run_server",
2041
- "kind": 2,
2042
- "importPath": "main",
2043
- "description": "main",
2044
- "peekOfCode": "def run_server():\n \"\"\"Run the MCP server with the configured settings.\"\"\"\n print(f\"Starting TutorX MCP server on {SERVER_HOST}:{SERVER_PORT}...\")\n print(f\"MCP transport: {SERVER_TRANSPORT}\")\n print(f\"API docs: http://{SERVER_HOST}:{SERVER_PORT}/docs\")\n print(f\"MCP endpoint: http://{SERVER_HOST}:{SERVER_PORT}/mcp\")\n # Configure uvicorn to run the FastAPI app\n uvicorn.run(\n \"server:api_app\",\n host=SERVER_HOST,",
2045
- "detail": "main",
2046
- "documentation": {}
2047
- },
2048
- {
2049
- "label": "SERVER_HOST",
2050
- "kind": 5,
2051
- "importPath": "main",
2052
- "description": "main",
2053
- "peekOfCode": "SERVER_HOST = os.getenv(\"MCP_HOST\", \"0.0.0.0\")\nSERVER_PORT = int(os.getenv(\"MCP_PORT\", \"8001\"))\nSERVER_TRANSPORT = os.getenv(\"MCP_TRANSPORT\", \"sse\")\ndef run_server():\n \"\"\"Run the MCP server with the configured settings.\"\"\"\n print(f\"Starting TutorX MCP server on {SERVER_HOST}:{SERVER_PORT}...\")\n print(f\"MCP transport: {SERVER_TRANSPORT}\")\n print(f\"API docs: http://{SERVER_HOST}:{SERVER_PORT}/docs\")\n print(f\"MCP endpoint: http://{SERVER_HOST}:{SERVER_PORT}/mcp\")\n # Configure uvicorn to run the FastAPI app",
2054
- "detail": "main",
2055
- "documentation": {}
2056
- },
2057
- {
2058
- "label": "SERVER_PORT",
2059
- "kind": 5,
2060
- "importPath": "main",
2061
- "description": "main",
2062
- "peekOfCode": "SERVER_PORT = int(os.getenv(\"MCP_PORT\", \"8001\"))\nSERVER_TRANSPORT = os.getenv(\"MCP_TRANSPORT\", \"sse\")\ndef run_server():\n \"\"\"Run the MCP server with the configured settings.\"\"\"\n print(f\"Starting TutorX MCP server on {SERVER_HOST}:{SERVER_PORT}...\")\n print(f\"MCP transport: {SERVER_TRANSPORT}\")\n print(f\"API docs: http://{SERVER_HOST}:{SERVER_PORT}/docs\")\n print(f\"MCP endpoint: http://{SERVER_HOST}:{SERVER_PORT}/mcp\")\n # Configure uvicorn to run the FastAPI app\n uvicorn.run(",
2063
- "detail": "main",
2064
- "documentation": {}
2065
- },
2066
- {
2067
- "label": "SERVER_TRANSPORT",
2068
- "kind": 5,
2069
- "importPath": "main",
2070
- "description": "main",
2071
- "peekOfCode": "SERVER_TRANSPORT = os.getenv(\"MCP_TRANSPORT\", \"sse\")\ndef run_server():\n \"\"\"Run the MCP server with the configured settings.\"\"\"\n print(f\"Starting TutorX MCP server on {SERVER_HOST}:{SERVER_PORT}...\")\n print(f\"MCP transport: {SERVER_TRANSPORT}\")\n print(f\"API docs: http://{SERVER_HOST}:{SERVER_PORT}/docs\")\n print(f\"MCP endpoint: http://{SERVER_HOST}:{SERVER_PORT}/mcp\")\n # Configure uvicorn to run the FastAPI app\n uvicorn.run(\n \"server:api_app\",",
2072
- "detail": "main",
2073
- "documentation": {}
2074
- },
2075
- {
2076
- "label": "run_mcp_server",
2077
- "kind": 2,
2078
- "importPath": "run",
2079
- "description": "run",
2080
- "peekOfCode": "def run_mcp_server(host=\"0.0.0.0\", port=8001):\n \"\"\"\n Run the MCP server using uvicorn\n Args:\n host: Host to bind the server to\n port: Port to run the server on\n \"\"\"\n print(f\"Starting TutorX MCP Server on {host}:{port}...\")\n # Set environment variables\n os.environ[\"MCP_HOST\"] = host",
2081
- "detail": "run",
2082
- "documentation": {}
2083
- },
2084
- {
2085
- "label": "run_gradio_interface",
2086
- "kind": 2,
2087
- "importPath": "run",
2088
- "description": "run",
2089
- "peekOfCode": "def run_gradio_interface(port=7860):\n \"\"\"\n Run the Gradio interface\n Args:\n port: Port to run the Gradio interface on\n \"\"\"\n print(f\"Starting TutorX Gradio Interface on port {port}...\")\n try:\n # Make sure the mcp-server directory is in the path\n mcp_server_dir = str(Path(__file__).parent / \"mcp-server\")",
2090
- "detail": "run",
2091
- "documentation": {}
2092
- },
2093
- {
2094
- "label": "check_port_available",
2095
- "kind": 2,
2096
- "importPath": "run",
2097
- "description": "run",
2098
- "peekOfCode": "def check_port_available(port):\n \"\"\"\n Check if a port is available\n Args:\n port: Port number to check\n Returns:\n bool: True if port is available, False otherwise\n \"\"\"\n with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\n return s.connect_ex(('localhost', port)) != 0",
2099
- "detail": "run",
2100
- "documentation": {}
2101
- },
2102
- {
2103
- "label": "run_tests",
2104
- "kind": 2,
2105
- "importPath": "run_tests",
2106
- "description": "run_tests",
2107
- "peekOfCode": "def run_tests():\n \"\"\"Run all tests\"\"\"\n print(\"Running TutorX-MCP Tests...\")\n # First run unittest tests\n unittest_loader = unittest.TestLoader()\n test_directory = os.path.join(os.path.dirname(__file__), \"tests\")\n test_suite = unittest_loader.discover(test_directory)\n test_runner = unittest.TextTestRunner(verbosity=2)\n unittest_result = test_runner.run(test_suite)\n # Then run pytest tests (with coverage)",
2108
- "detail": "run_tests",
2109
- "documentation": {}
2110
- }
2111
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
PROJECT_ANALYSIS.md ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # TutorX-MCP Project Analysis
2
+
3
+ ## Table of Contents
4
+ 1. [Executive Summary](#executive-summary)
5
+ 2. [Software Architecture Analysis](#software-architecture-analysis)
6
+ 3. [Implementation Analysis](#implementation-analysis)
7
+ 4. [Product Analysis](#product-analysis)
8
+ 5. [Recommendations](#recommendations)
9
+ 6. [Version History](#version-history)
10
+
11
+ ## Executive Summary
12
+
13
+ TutorX-MCP is an advanced educational AI tutoring platform that leverages the Model Context Protocol (MCP) for tool integration and provides a comprehensive suite of educational features. The system follows a modern architecture with a clear separation of concerns between the MCP server, tool implementations, and user interfaces.
14
+
15
+ The project implements a range of features as described in the Product Requirements Document (PRD), including an adaptive learning engine, multi-modal interaction capabilities, assessment tools, and advanced features like document OCR and submission originality checking.
16
+
17
+ This analysis examines the project from three perspectives:
18
+ 1. **Software Architecture**: Evaluating system design, component interactions, and architectural decisions
19
+ 2. **Implementation**: Reviewing code quality, patterns, and technical choices
20
+ 3. **Product**: Assessing feature completeness, user experience, and alignment with requirements
21
+
22
+ ## Software Architecture Analysis
23
+
24
+ ### System Architecture Overview
25
+
26
+ ```mermaid
27
+ graph TD
28
+ Client[Client Applications] --> |HTTP/SSE| MCP[MCP Server]
29
+ GradioUI[Gradio Web Interface] --> |HTTP| MCP
30
+
31
+ MCP --> ModelLayer[Model Layer]
32
+ MCP --> ToolLayer[Tool Layer]
33
+ MCP --> ResourceLayer[Resource Layer]
34
+
35
+ ModelLayer --> |API Calls| Gemini[Google Gemini]
36
+ ModelLayer --> |API Calls| MistralOCR[Mistral OCR]
37
+
38
+ ToolLayer --> ConceptTools[Concept Tools]
39
+ ToolLayer --> QuizTools[Quiz Tools]
40
+ ToolLayer --> LessonTools[Lesson Tools]
41
+ ToolLayer --> OCRTools[OCR Tools]
42
+ ToolLayer --> InteractionTools[Interaction Tools]
43
+ ToolLayer --> LearningPathTools[Learning Path Tools]
44
+
45
+ ResourceLayer --> ConceptGraph[Concept Graph]
46
+ ResourceLayer --> CurriculumStandards[Curriculum Standards]
47
+ ResourceLayer --> MemoryBank[Memory Bank*]
48
+
49
+ style MemoryBank fill:#f9f,stroke:#333,stroke-dasharray: 5 5
50
+ ```
51
+
52
+ ### Component Analysis
53
+
54
+ #### MCP Server
55
+ The MCP server is the core of the system, implemented using FastAPI and FastMCP. It handles HTTP requests, manages tool registration, and exposes endpoints for client applications. Key architectural aspects include:
56
+
57
+ 1. **Shared MCP Instance**: The system uses a single shared MCP instance (`mcp_instance.py`) to avoid circular imports and ensure all tools are available to the running server.
58
+
59
+ 2. **API Gateway**: The server acts as an API gateway, exposing HTTP endpoints for all core features.
60
+
61
+ 3. **SSE Transport**: The server provides Server-Sent Events (SSE) transport for protocol-compliant client connections.
62
+
63
+ ```mermaid
64
+ sequenceDiagram
65
+ participant Client
66
+ participant APIGateway as API Gateway
67
+ participant MCPServer as MCP Server
68
+ participant Tool as Tool Implementation
69
+ participant Model as AI Model
70
+
71
+ Client->>APIGateway: HTTP Request
72
+ APIGateway->>MCPServer: Forward Request
73
+ MCPServer->>Tool: Execute Tool Function
74
+ Tool->>Model: Generate Content (if needed)
75
+ Model-->>Tool: Model Response
76
+ Tool-->>MCPServer: Tool Result
77
+ MCPServer-->>APIGateway: Format Response
78
+ APIGateway-->>Client: HTTP Response
79
+ ```
80
+
81
+ #### Tool Layer
82
+ Tools are implemented as async functions decorated with `@mcp.tool()` and organized by functionality in the `tools` directory. This modular design allows for easy extension and maintenance:
83
+
84
+ 1. **Concept Tools**: Handle concept graph interactions and skill assessments
85
+ 2. **Quiz Tools**: Generate educational quizzes based on concepts
86
+ 3. **Lesson Tools**: Create complete lesson plans
87
+ 4. **OCR Tools**: Process documents and extract text using Mistral OCR
88
+ 5. **Interaction Tools**: Process student queries and check submission originality
89
+ 6. **Learning Path Tools**: Generate personalized learning paths
90
+
91
+ #### Resource Layer
92
+ Resources are managed as in-memory data structures that provide access to educational content:
93
+
94
+ 1. **Concept Graph**: Maintains relationships between educational concepts
95
+ 2. **Curriculum Standards**: Stores educational standards for different countries
96
+ 3. **Memory Bank**: Planned feature for persistent storage of student interactions
97
+
98
+ #### Model Layer
99
+ The system integrates with AI models through a well-designed abstraction layer:
100
+
101
+ 1. **GeminiFlash Class**: Provides a unified interface to Google's Gemini models with automatic fallback from Gemini 2.0 to 1.5 when necessary.
102
+ 2. **Mistral OCR Integration**: External OCR service for document processing.
103
+
104
+ ### Architectural Patterns
105
+
106
+ The TutorX-MCP system implements several notable architectural patterns:
107
+
108
+ 1. **Microservices Architecture**: The system is designed with modular components that can be independently deployed and scaled.
109
+
110
+ 2. **API Gateway Pattern**: The MCP server functions as an API gateway, providing a unified entry point for clients.
111
+
112
+ 3. **Decorator Pattern**: Used for tool registration through the `@mcp.tool()` decorator.
113
+
114
+ 4. **Dependency Injection**: The shared MCP instance is injected into tool modules.
115
+
116
+ 5. **Circuit Breaker Pattern**: The Gemini model implementation includes fallback mechanisms when the primary model fails.
117
+
118
+ ### Strengths
119
+
120
+ 1. **Modularity**: Clear separation of concerns with distinct modules for different responsibilities.
121
+ 2. **Extensibility**: New tools can be easily added by creating new functions and registering them with the MCP instance.
122
+ 3. **Error Handling**: Robust error handling and fallback mechanisms for external services.
123
+ 4. **API-First Design**: All features are accessible via well-defined API endpoints.
124
+
125
+ ### Areas for Improvement
126
+
127
+ 1. **Memory Bank Implementation**: The memory bank feature is planned but not yet implemented, limiting stateful interactions.
128
+ 2. **Resource Persistence**: Resources are currently in-memory, which limits scalability and persistence.
129
+ 3. **Authentication & Authorization**: Limited security mechanisms for protecting sensitive endpoints.
130
+ 4. **Testing Coverage**: While test infrastructure exists, more comprehensive test coverage would improve reliability.
131
+
132
+ ## Implementation Analysis
133
+
134
+ ### Code Organization
135
+
136
+ The project follows a well-structured organization:
137
+
138
+ ```
139
+ tutorx-mcp/
140
+ ├── main.py # MCP server entry point
141
+ ├── app.py # Gradio web interface
142
+ ├── run.py # Runner script for different modes
143
+ ├── tests/ # Test suite
144
+ ├── mcp_server/ # Core server implementation
145
+ │ ├── server.py # FastAPI application
146
+ │ ├── mcp_instance.py # Shared MCP instance
147
+ │ ├── model/ # Model integration
148
+ │ ├── resources/ # Educational resources
149
+ │ └── tools/ # MCP tool implementations
150
+ └── docs/ # Documentation
151
+ ```
152
+
153
+ ### Technology Stack
154
+
155
+ 1. **Backend Framework**: FastAPI for high-performance API endpoints
156
+ 2. **MCP Implementation**: FastMCP for Model Context Protocol support
157
+ 3. **UI Framework**: Gradio for web interface
158
+ 4. **AI Models**: Google Gemini 2.0 Flash with fallback to 1.5
159
+ 5. **OCR Service**: Mistral OCR for document processing
160
+ 6. **Testing**: Pytest and unittest for test automation
161
+
162
+ ### Code Quality Assessment
163
+
164
+ #### Strengths
165
+ 1. **Type Hints**: Consistent use of typing annotations for better IDE support and documentation
166
+ 2. **Error Handling**: Comprehensive error catching and fallback mechanisms
167
+ 3. **Code Organization**: Logical separation of concerns
168
+ 4. **Documentation**: Detailed docstrings and comments
169
+
170
+ #### Areas for Improvement
171
+ 1. **Model API Key Management**: Hard-coded API key in the code (`gemini_flash.py`)
172
+ 2. **Consistent JSON Parsing**: Multiple implementations of JSON extraction methods across modules
173
+ 3. **Test Coverage**: Some modules lack comprehensive tests
174
+
175
+ ### Implementation Patterns
176
+
177
+ 1. **Asynchronous Programming**: Consistent use of `async`/`await` for non-blocking operations
178
+ 2. **Singleton Pattern**: Shared MCP instance as a singleton
179
+ 3. **Factory Pattern**: For creating various educational resources
180
+ 4. **Strategy Pattern**: For different model versions and fallback mechanisms
181
+
182
+ ## Product Analysis
183
+
184
+ ### Feature Completeness
185
+
186
+ The implemented features align well with the PRD requirements:
187
+
188
+ #### Core Features
189
+ ✓ **Adaptive Learning Engine**: Implemented with concept graph and learning paths
190
+ ✓ **Multi-Modal Interaction**: Text processing and OCR integration
191
+ ✓ **Assessment Suite**: Quiz generation and originality checking
192
+ ✓ **Feedback System**: Contextual analysis of student submissions
193
+
194
+ #### Advanced Features
195
+ ✓ **Cross-Institutional Knowledge Fusion**: Curriculum standards for multiple countries
196
+ ✓ **Automated Lesson Authoring**: Lesson generation based on topic and grade level
197
+ ⚠️ **Neurological Engagement Monitor**: Not fully implemented
198
+
199
+ ### User Experience Analysis
200
+
201
+ The platform provides multiple access methods:
202
+ 1. **MCP Client Access**: Through the MCP protocol for AI assistants
203
+ 2. **Web Interface**: Through Gradio for direct user interaction
204
+
205
+ ```mermaid
206
+ graph LR
207
+ User -->|Direct Access| WebUI[Web Interface]
208
+ User -->|AI Assistant| MCPClient[MCP Client]
209
+
210
+ WebUI -->|HTTP| APIEndpoints[API Endpoints]
211
+ MCPClient -->|MCP Protocol| SSETransport[SSE Transport]
212
+
213
+ APIEndpoints --> MCPServer[MCP Server]
214
+ SSETransport --> MCPServer
215
+ ```
216
+
217
+ ### Alignment with Target Users
218
+
219
+ The system caters well to the three primary user groups:
220
+
221
+ 1. **Students**: Through personalized learning paths and multi-modal interaction
222
+ 2. **Teachers**: Through assessment tools and curriculum alignment
223
+ 3. **Administrators**: Through curriculum standards integration
224
+
225
+ ### Market Positioning
226
+
227
+ TutorX-MCP positions itself as a comprehensive educational platform with these unique selling points:
228
+ 1. **AI-Powered Adaptivity**: Personalized learning based on student needs
229
+ 2. **Multi-Modal Interaction**: Supporting various input methods
230
+ 3. **MCP Integration**: Enabling use within AI assistants
231
+ 4. **Cross-Standard Support**: Accommodating different educational systems
232
+
233
+ ## Recommendations
234
+
235
+ ### Architectural Recommendations
236
+
237
+ 1. **Implement Memory Bank**: Complete the planned Memory Bank feature for persistent storage of student interactions and learning progress.
238
+
239
+ 2. **Database Integration**: Move from in-memory resources to a proper database for the concept graph and curriculum standards.
240
+
241
+ 3. **Authentication Layer**: Add proper authentication and authorization mechanisms to protect sensitive endpoints.
242
+
243
+ 4. **Resource Caching**: Implement a caching strategy for frequently accessed resources.
244
+
245
+ ```mermaid
246
+ graph TD
247
+ MCP[MCP Server] --> Auth[Authentication Layer]
248
+ Auth --> Cache[Cache Layer]
249
+ Cache --> DB[(Database)]
250
+ Cache --> Tools[Tool Implementations]
251
+ Tools --> Models[AI Models]
252
+ ```
253
+
254
+ ### Implementation Recommendations
255
+
256
+ 1. **Credential Management**: Move API keys to environment variables or a secure credential store.
257
+
258
+ 2. **Common Utilities**: Create a shared utilities module for common functions like JSON parsing.
259
+
260
+ 3. **Enhanced Testing**: Increase test coverage, especially for critical paths.
261
+
262
+ 4. **CI/CD Pipeline**: Set up continuous integration and deployment processes.
263
+
264
+ ### Product Recommendations
265
+
266
+ 1. **Complete Multi-Modal Support**: Add voice recognition capability to complement text and OCR.
267
+
268
+ 2. **User Dashboard**: Implement the custom dashboard described in the PRD.
269
+
270
+ 3. **Access Control**: Add role-based access control for different user types.
271
+
272
+ 4. **Metrics Collection**: Implement logging and metrics to track system usage and performance.
273
+
274
+ ## Version History
275
+
276
+ ### v0.1.0 (Initial Release) - June 2025
277
+ - Implemented core MCP server with tool registration
278
+ - Added concept graph and curriculum standards resources
279
+ - Integrated Google Gemini Flash models with fallback mechanism
280
+ - Implemented basic tools (concept, quiz, lesson generation)
281
+ - Added Mistral OCR integration for document processing
282
+ - Created basic test suite with unittest and pytest
283
+
284
+ ### v0.2.0 (Planned) - July 2025
285
+ - Memory Bank implementation for persistent storage
286
+ - Enhanced multi-modal support with voice recognition
287
+ - Improved test coverage and CI/CD pipeline
288
+ - User dashboard implementation
289
+ - Role-based access control
README.md CHANGED
@@ -8,6 +8,27 @@ TutorX-MCP is an adaptive, multi-modal, and collaborative AI tutoring platform t
8
 
9
  ![TutorX-MCP](https://via.placeholder.com/800x400?text=TutorX-MCP+Educational+Platform)
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  ## Features
12
 
13
  ### Core Features
@@ -50,109 +71,182 @@ TutorX-MCP is an adaptive, multi-modal, and collaborative AI tutoring platform t
50
  - Python 3.12 or higher
51
  - Dependencies as listed in pyproject.toml:
52
  - mcp[cli] >= 1.9.3
 
 
53
  - gradio >= 4.19.0
54
  - numpy >= 1.24.0
55
  - pillow >= 10.0.0
 
 
56
 
57
  ### Installation
58
 
59
- ```bash
60
  # Clone the repository
61
- git clone https://github.com/yourusername/tutorx-mcp.git
62
  cd tutorx-mcp
63
 
64
  # Using uv (recommended)
65
  uv install
66
 
67
- # Or using pip
68
- pip install -e .
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  ```
70
 
71
  ### Running the Server
72
 
73
  You can run the server in different modes:
74
 
75
- ```bash
76
  # MCP server only
77
  python run.py --mode mcp
78
 
79
  # Gradio interface only
80
  python run.py --mode gradio
81
 
82
- # Both MCP server and Gradio interface
83
  python run.py --mode both
84
 
85
  # Custom host and port
86
- python run.py --mode mcp --host 0.0.0.0 --port 9000
87
  ```
88
 
89
- By default, the MCP server will run at http://localhost:8000 and the Gradio interface at http://127.0.0.1:7860.
 
 
 
90
 
91
  ## MCP Tool Integration
92
 
93
  The server exposes the following MCP tools and resources:
94
 
95
  ### Tools
96
- - **Core Features**
97
- - `assess_skill`: Evaluate student's skill level on specific concepts
98
- - `generate_quiz`: Create quizzes for specific concepts
99
- - `analyze_error_patterns`: Find common student mistakes
100
-
101
- - **Assessment**
102
- - `create_assessment`: Generate complete assessments
103
- - `grade_assessment`: Score student responses
104
- - `check_submission_originality`: Detect plagiarism
105
-
106
- - **Advanced Features**
107
- - `analyze_cognitive_state`: Process EEG data
108
- - `align_content_to_standard`: Match content to curriculum standards
109
- - `generate_lesson`: Create complete lesson plans
110
-
111
- - **Multi-Modal**
112
- - `text_interaction`: Process text queries
113
- - `voice_interaction`: Handle voice input
114
- - `handwriting_recognition`: Process handwritten input
 
 
 
 
 
 
 
115
 
116
  ### Resources
117
- - `concept-graph://`: Knowledge concept graph
118
- - `learning-path://{student_id}`: Personalized learning paths
119
- - `curriculum-standards://{country_code}`: National curricular standards
120
- - `student-dashboard://{student_id}`: Student performance dashboard
 
121
 
122
  ## Project Structure
123
 
124
  ```
125
  tutorx-mcp/
126
- ├── main.py # MCP server implementation
127
- ├── client.py # MCP client for calling server tools
128
- ├── app.py # Gradio web interface
129
- ├── run.py # Runner script for different modes
130
- ├── tests/ # Test suite
131
- │ ├── test_mcp_server.py # MCP server tests
132
- │ ├── test_client.py # Client tests
133
- │ └── test_utils.py # Utility function tests
134
- ├── utils/ # Utility modules
135
- │ ├── multimodal.py # Multi-modal processing utilities
136
- │ └── assessment.py # Assessment and analytics functions
137
- ├── pyproject.toml # Project dependencies
138
- ├── run_tests.py # Script to run all tests
139
- └── README.md # Project documentation
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  ```
141
 
142
  ## Architecture
143
 
144
- The TutorX-MCP follows a layered architecture:
 
 
145
 
146
- 1. **MCP Server (main.py)**: Core backend that exposes educational tools and resources through the Model Context Protocol.
 
 
 
147
 
148
- 2. **MCP Client (client.py)**: Client library that communicates with the MCP server through HTTP requests, translating method calls into MCP protocol interactions.
 
 
149
 
150
- 3. **Gradio Interface (app.py)**: Web-based user interface that uses the client to communicate with the MCP server.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
 
152
  This separation of concerns allows:
153
- - MCP clients (like Claude Desktop App) to directly connect to the MCP server
154
- - The web interface to interact with the server using standard HTTP
155
- - Clear boundaries between presentation, business logic, and tool implementation
 
 
 
156
 
157
  ## Testing
158
 
@@ -166,13 +260,13 @@ uv install -e ".[test]"
166
  python run_tests.py
167
  ```
168
 
169
-
170
-
171
  ## Documentation
172
 
 
173
  - [MCP Protocol](docs/mcp.md): Details about the Model Context Protocol
174
  - [Product Requirements](docs/prd.md): Original requirements document
175
  - [SDK Documentation](docs/sdk.md): Client SDK usage
 
176
 
177
  ## Contributing
178
 
 
8
 
9
  ![TutorX-MCP](https://via.placeholder.com/800x400?text=TutorX-MCP+Educational+Platform)
10
 
11
+ For a comprehensive analysis of the project from architectural, development, and product perspectives, please see our [Project Analysis Document](PROJECT_ANALYSIS.md).
12
+
13
+ ## Version History
14
+
15
+ ### Current Version
16
+ - **v0.1.0** (June 2025)
17
+ - Initial release of core MCP server with SSE transport
18
+ - Implementation of concept graph and curriculum standards resources
19
+ - Integration with Google Gemini Flash models (with fallback mechanism)
20
+ - Addition of Mistral OCR for document processing
21
+ - Core educational tools: concepts, quizzes, lessons, learning paths
22
+ - Basic testing framework with pytest and unittest
23
+
24
+ ### Upcoming Release
25
+ - **v0.2.0** (Planned - July 2025)
26
+ - Memory Bank implementation for persistent context storage
27
+ - Enhanced multi-modal support with voice recognition
28
+ - Improved testing coverage and CI/CD pipeline
29
+ - User dashboard implementation
30
+ - Role-based access control and security enhancements
31
+
32
  ## Features
33
 
34
  ### Core Features
 
71
  - Python 3.12 or higher
72
  - Dependencies as listed in pyproject.toml:
73
  - mcp[cli] >= 1.9.3
74
+ - fastapi >= 0.109.0
75
+ - uvicorn >= 0.27.0
76
  - gradio >= 4.19.0
77
  - numpy >= 1.24.0
78
  - pillow >= 10.0.0
79
+ - google-generativeai (for Gemini integration)
80
+ - mistralai (for OCR capabilities)
81
 
82
  ### Installation
83
 
84
+ ```powershell
85
  # Clone the repository
86
+ git clone https://github.com/Meetpatel006/TutorX.git
87
  cd tutorx-mcp
88
 
89
  # Using uv (recommended)
90
  uv install
91
 
92
+ ```
93
+
94
+ ### Required API Keys
95
+
96
+ For full functionality, you'll need to set up the following API keys:
97
+
98
+ - **Google AI API Key**: For Gemini Flash model integration
99
+ - **Mistral API Key**: For document OCR capabilities
100
+
101
+ These can be set as environment variables or in an `.env` file:
102
+
103
+ ```powershell
104
+ # PowerShell example
105
+ $env:GOOGLE_API_KEY="your-google-api-key"
106
+ $env:MISTRAL_API_KEY="your-mistral-api-key"
107
  ```
108
 
109
  ### Running the Server
110
 
111
  You can run the server in different modes:
112
 
113
+ ```powershell
114
  # MCP server only
115
  python run.py --mode mcp
116
 
117
  # Gradio interface only
118
  python run.py --mode gradio
119
 
120
+ # Both MCP server and Gradio interface (default)
121
  python run.py --mode both
122
 
123
  # Custom host and port
124
+ python run.py --mode mcp --host 0.0.0.0 --mcp-port 8001 --gradio-port 7860
125
  ```
126
 
127
+ By default:
128
+ - The MCP server runs at http://localhost:8001
129
+ - SSE transport is available at http://localhost:8001/sse
130
+ - The Gradio interface runs at http://127.0.0.1:7860
131
 
132
  ## MCP Tool Integration
133
 
134
  The server exposes the following MCP tools and resources:
135
 
136
  ### Tools
137
+
138
+ - **Concept Tools** (concept_tools.py)
139
+ - `get_concept_tool`: Retrieve detailed information about educational concepts
140
+ - `assess_skill_tool`: Evaluate student's understanding of specific concepts
141
+
142
+ - **Quiz Tools** (quiz_tools.py)
143
+ - `generate_quiz_tool`: Create LLM-generated quizzes for specific concepts with customizable difficulty
144
+
145
+ - **Lesson Tools** (lesson_tools.py)
146
+ - `generate_lesson_tool`: Create complete lesson plans with objectives, activities, and assessments
147
+
148
+ - **Interaction Tools** (interaction_tools.py)
149
+ - `text_interaction`: Process student text queries and provide educational responses
150
+ - `check_submission_originality`: Analyze student submissions for potential plagiarism
151
+
152
+ - **OCR Tools** (ocr_tools.py)
153
+ - `mistral_document_ocr`: Extract and process text from documents using Mistral OCR
154
+
155
+ - **Learning Path Tools** (learning_path_tools.py)
156
+ - `get_learning_path`: Generate personalized learning paths based on student level and target concepts
157
+
158
+ - **Memory Tools** (v0.2.0)
159
+ - `read_memory_tool`: Retrieve stored context from the Memory Bank
160
+ - `write_memory_tool`: Store new contextual information in the Memory Bank
161
+ - `update_memory_tool`: Modify existing context in the Memory Bank
162
+ - `clear_memory_tool`: Remove stored context from the Memory Bank
163
 
164
  ### Resources
165
+
166
+ - `concept-graph://`: Knowledge concept graph with concept relationships
167
+ - `curriculum-standards://{country_code}`: National curricular standards by country
168
+ - `learning-path://{student_id}`: Personalized student learning paths
169
+
170
 
171
  ## Project Structure
172
 
173
  ```
174
  tutorx-mcp/
175
+ ├── main.py # MCP server entry point
176
+ ├── app.py # Gradio web interface
177
+ ├── run.py # Runner script for different modes
178
+ ├── mcp_server/ # Core server implementation
179
+ ├── server.py # FastAPI application
180
+ │ ├── mcp_instance.py # Shared MCP instance
181
+ │ ├── model/ # AI model integrations
182
+ └── gemini_flash.py # Google Gemini integration
183
+ ├── resources/ # Educational resources
184
+ ├── concept_graph.py # Concept graph implementation
185
+ └── curriculum_standards.py # Curriculum standards
186
+ ├── tools/ # MCP tool implementations
187
+ │ │ ├── concept_tools.py # Concept-related tools
188
+ │ │ ├── quiz_tools.py # Quiz generation tools
189
+ │ │ ├── lesson_tools.py # Lesson generation tools
190
+ │ │ ├── ocr_tools.py # Document OCR tools
191
+ │ │ ├── interaction_tools.py # Student interaction tools
192
+ │ │ └── learning_path_tools.py # Learning path tools
193
+ │ └── prompts/ # LLM prompt templates
194
+ ├── tests/ # Test suite
195
+ │ ├── test_mcp_server.py # MCP server tests
196
+ │ ├── test_client.py # Client tests
197
+ │ ├── test_tools_integration.py # Tool integration tests
198
+ │ └── test_utils.py # Utility function tests
199
+ ├── docs/ # Documentation
200
+ │ ├── API.md # API documentation
201
+ │ ├── mcp.md # MCP protocol details
202
+ │ ├── prd.md # Product requirements document
203
+ │ └── sdk.md # Client SDK documentation
204
+ ├── pyproject.toml # Project dependencies
205
+ ├── run_tests.py # Script to run all tests
206
+ ├── ARCHITECTURE.md # Detailed architecture documentation
207
+ ├── PROJECT_ANALYSIS.md # Comprehensive project analysis
208
+ └── README.md # Project documentation
209
  ```
210
 
211
  ## Architecture
212
 
213
+ TutorX-MCP implements a modular, layered architecture designed for extensibility and maintainability:
214
+
215
+ ### Key Components
216
 
217
+ 1. **MCP Server (mcp_server/server.py)**:
218
+ - Core FastAPI application that exposes educational tools and resources
219
+ - Registers tools with the shared MCP instance
220
+ - Provides HTTP endpoints and SSE transport for client connections
221
 
222
+ 2. **Shared MCP Instance (mcp_server/mcp_instance.py)**:
223
+ - Central registration point for all MCP tools
224
+ - Avoids circular import issues and ensures tool availability
225
 
226
+ 3. **AI Model Integration (mcp_server/model/)**:
227
+ - Integrates Google Gemini Flash models with automatic fallback mechanisms
228
+ - Provides uniform interface for text generation and content structuring
229
+
230
+ 4. **Tool Modules (mcp_server/tools/)**:
231
+ - Modular implementation of educational features
232
+ - Each tool is registered with the MCP instance via decorators
233
+ - Designed for independent development and testing
234
+
235
+ 5. **Resource Modules (mcp_server/resources/)**:
236
+ - Manages educational data like concept graphs and curriculum standards
237
+ - Provides data for adaptive learning and standards alignment
238
+
239
+ 6. **Gradio Interface (app.py)**:
240
+ - Web-based user interface
241
+ - Communicates with the MCP server via the MCP client protocol
242
 
243
  This separation of concerns allows:
244
+ - MCP clients (like Claude Desktop App) to directly connect to the MCP server via SSE transport
245
+ - The web interface to interact with the server using the MCP protocol
246
+ - Clear boundaries between presentation, API gateway, tool implementations, and resources
247
+ - Easy extension through the addition of new tool modules
248
+
249
+ For more detailed architecture information, see the [Architecture Documentation](ARCHITECTURE.md) and [Project Analysis](PROJECT_ANALYSIS.md).
250
 
251
  ## Testing
252
 
 
260
  python run_tests.py
261
  ```
262
 
 
 
263
  ## Documentation
264
 
265
+ - [Project Analysis](PROJECT_ANALYSIS.md): Comprehensive analysis of architecture, implementation, and product features
266
  - [MCP Protocol](docs/mcp.md): Details about the Model Context Protocol
267
  - [Product Requirements](docs/prd.md): Original requirements document
268
  - [SDK Documentation](docs/sdk.md): Client SDK usage
269
+ - [Architecture](ARCHITECTURE.md): Detailed technical architecture documentation
270
 
271
  ## Contributing
272
 
run.py CHANGED
@@ -4,50 +4,64 @@ Script to run either the MCP server or the Gradio interface for TutorX
4
 
5
  import os
6
  import sys
 
7
  import argparse
8
- import uvicorn
 
9
  from pathlib import Path
10
  import socket
11
 
12
- def run_mcp_server(host="0.0.0.0", port=8001):
13
  """
14
- Run the MCP server using uvicorn
15
 
16
  Args:
17
  host: Host to bind the server to
18
  port: Port to run the server on
 
19
  """
20
  print(f"Starting TutorX MCP Server on {host}:{port}...")
21
 
22
  # Set environment variables
23
  os.environ["MCP_HOST"] = host
24
  os.environ["MCP_PORT"] = str(port)
 
 
25
 
26
  try:
27
- # Add the mcp-server directory to Python path
28
- mcp_server_dir = str(Path(__file__).parent / "mcp-server")
29
- if mcp_server_dir not in sys.path:
30
- sys.path.insert(0, mcp_server_dir)
 
 
31
 
32
- # Import the FastAPI app
33
- from server import api_app
 
34
 
35
- # Run the server using uvicorn
36
- uvicorn.run(
37
- "mcp-server.server:api_app",
38
- host=host,
39
- port=port,
40
- reload=True,
41
- reload_dirs=[mcp_server_dir],
42
- log_level="info"
43
  )
44
- except ImportError as e:
45
- print(f"Error: {e}")
46
- print("Make sure you have installed all required dependencies:")
47
- print(" pip install uvicorn fastapi")
48
- sys.exit(1)
 
 
 
 
 
 
49
  except Exception as e:
50
  print(f"Error starting MCP server: {e}")
 
 
51
  sys.exit(1)
52
 
53
  def run_gradio_interface(port=7860):
@@ -60,8 +74,8 @@ def run_gradio_interface(port=7860):
60
  print(f"Starting TutorX Gradio Interface on port {port}...")
61
 
62
  try:
63
- # Make sure the mcp-server directory is in the path
64
- mcp_server_dir = str(Path(__file__).parent / "mcp-server")
65
  if mcp_server_dir not in sys.path:
66
  sys.path.insert(0, mcp_server_dir)
67
 
@@ -123,6 +137,12 @@ if __name__ == "__main__":
123
  help="Port for Gradio interface (default: 7860)"
124
  )
125
 
 
 
 
 
 
 
126
  args = parser.parse_args()
127
 
128
  # Check if ports are available
@@ -134,23 +154,26 @@ if __name__ == "__main__":
134
  print(f"Error: Port {args.gradio_port} is already in use (Gradio interface)")
135
  sys.exit(1)
136
 
 
 
137
  try:
138
  if args.mode in ["mcp", "both"]:
139
- # Start MCP server in a separate process
140
- mcp_process = multiprocessing.Process(
141
- target=run_mcp_server,
142
- kwargs={
143
- "host": args.host,
144
- "port": args.mcp_port
145
- }
146
  )
147
- mcp_process.start()
148
 
149
  # Give the server a moment to start
150
  time.sleep(2)
 
 
151
 
152
  if args.mode in ["gradio", "both"]:
153
  # Run Gradio in the main process
 
154
  run_gradio_interface(port=args.gradio_port)
155
 
156
  except KeyboardInterrupt:
@@ -159,6 +182,12 @@ if __name__ == "__main__":
159
  print(f"Error: {e}")
160
  sys.exit(1)
161
  finally:
162
- if 'mcp_process' in locals() and mcp_process.is_alive():
163
- mcp_process.terminate()
164
- mcp_process.join(timeout=5)
 
 
 
 
 
 
 
4
 
5
  import os
6
  import sys
7
+ import time
8
  import argparse
9
+ import subprocess
10
+ import multiprocessing
11
  from pathlib import Path
12
  import socket
13
 
14
+ def run_mcp_server(host="0.0.0.0", port=8001, debug=False):
15
  """
16
+ Run the MCP server using uv
17
 
18
  Args:
19
  host: Host to bind the server to
20
  port: Port to run the server on
21
+ debug: Whether to run in debug mode
22
  """
23
  print(f"Starting TutorX MCP Server on {host}:{port}...")
24
 
25
  # Set environment variables
26
  os.environ["MCP_HOST"] = host
27
  os.environ["MCP_PORT"] = str(port)
28
+ if debug:
29
+ os.environ["DEBUG"] = "1"
30
 
31
  try:
32
+ # Build the command to run the server using uv
33
+ cmd = [
34
+ "uv", "run", "-m", "mcp_server.server",
35
+ "--host", host,
36
+ "--port", str(port)
37
+ ]
38
 
39
+ # Add debug flag if needed
40
+ if debug:
41
+ cmd.append("--debug")
42
 
43
+ # Execute the command
44
+ server_process = subprocess.Popen(
45
+ cmd,
46
+ stdout=subprocess.PIPE,
47
+ stderr=subprocess.STDOUT,
48
+ universal_newlines=True
 
 
49
  )
50
+
51
+ # Print the first few lines of output to confirm server started
52
+ for _ in range(5):
53
+ line = server_process.stdout.readline()
54
+ if not line:
55
+ break
56
+ print(line.strip())
57
+
58
+ # Return the process so it can be managed by the caller
59
+ return server_process
60
+
61
  except Exception as e:
62
  print(f"Error starting MCP server: {e}")
63
+ print("Make sure you have installed all required dependencies:")
64
+ print(" pip install uv")
65
  sys.exit(1)
66
 
67
  def run_gradio_interface(port=7860):
 
74
  print(f"Starting TutorX Gradio Interface on port {port}...")
75
 
76
  try:
77
+ # Make sure the mcp_server directory is in the path
78
+ mcp_server_dir = str(Path(__file__).parent / "mcp_server")
79
  if mcp_server_dir not in sys.path:
80
  sys.path.insert(0, mcp_server_dir)
81
 
 
137
  help="Port for Gradio interface (default: 7860)"
138
  )
139
 
140
+ parser.add_argument(
141
+ "--debug",
142
+ action="store_true",
143
+ help="Run with debug mode for more verbose output"
144
+ )
145
+
146
  args = parser.parse_args()
147
 
148
  # Check if ports are available
 
154
  print(f"Error: Port {args.gradio_port} is already in use (Gradio interface)")
155
  sys.exit(1)
156
 
157
+ server_process = None
158
+
159
  try:
160
  if args.mode in ["mcp", "both"]:
161
+ # Start MCP server using uv run
162
+ print("Starting MCP server...")
163
+ server_process = run_mcp_server(
164
+ host=args.host,
165
+ port=args.mcp_port,
166
+ debug=args.debug
 
167
  )
 
168
 
169
  # Give the server a moment to start
170
  time.sleep(2)
171
+ print(f"MCP server running at http://{args.host}:{args.mcp_port}")
172
+ print(f"MCP SSE endpoint available at http://{args.host}:{args.mcp_port}/sse")
173
 
174
  if args.mode in ["gradio", "both"]:
175
  # Run Gradio in the main process
176
+ print(f"Starting Gradio interface on port {args.gradio_port}...")
177
  run_gradio_interface(port=args.gradio_port)
178
 
179
  except KeyboardInterrupt:
 
182
  print(f"Error: {e}")
183
  sys.exit(1)
184
  finally:
185
+ # Clean up the server process if it's running
186
+ if server_process is not None:
187
+ print("Terminating MCP server...")
188
+ server_process.terminate()
189
+ try:
190
+ server_process.wait(timeout=5)
191
+ except subprocess.TimeoutExpired:
192
+ server_process.kill()
193
+ print("Server process killed after timeout")