Spaces:
Sleeping
Sleeping
Meet Patel
commited on
Commit
·
71c0fd0
1
Parent(s):
3d56f3d
Fix some major issue with api and integrations
Browse files- .coverage +0 -0
- README.md +1 -16
- client.py +2 -49
- docs/api.md +0 -368
- docs/prd.md +2 -16
- main.py +2 -122
- utils/integrations.py +0 -251
.coverage
ADDED
Binary file (53.2 kB). View file
|
|
README.md
CHANGED
@@ -166,25 +166,10 @@ uv install -e ".[test]"
|
|
166 |
python run_tests.py
|
167 |
```
|
168 |
|
169 |
-
|
170 |
-
|
171 |
-
TutorX-MCP can integrate with various external educational systems:
|
172 |
-
|
173 |
-
1. **Learning Management Systems (LMS)**
|
174 |
-
- Canvas, Moodle, Blackboard
|
175 |
-
- Grade syncing and assignment management
|
176 |
-
|
177 |
-
2. **Open Educational Resources (OER)**
|
178 |
-
- Search and integration with OER repositories
|
179 |
-
- Access to diverse educational content
|
180 |
-
|
181 |
-
3. **Real-time Personalized Tutoring Platforms**
|
182 |
-
- Schedule and manage tutoring sessions
|
183 |
-
- Connect students with expert tutors
|
184 |
|
185 |
## Documentation
|
186 |
|
187 |
-
- [API Documentation](docs/api.md): Complete API reference for developers
|
188 |
- [MCP Protocol](docs/mcp.md): Details about the Model Context Protocol
|
189 |
- [Product Requirements](docs/prd.md): Original requirements document
|
190 |
- [SDK Documentation](docs/sdk.md): Client SDK usage
|
|
|
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
|
client.py
CHANGED
@@ -190,60 +190,13 @@ class TutorXClient:
|
|
190 |
return self._call_tool("get_student_analytics", {
|
191 |
"student_id": student_id,
|
192 |
"timeframe_days": timeframe_days
|
193 |
-
})
|
194 |
-
|
195 |
"""Check student submission for potential plagiarism"""
|
196 |
return self._call_tool("check_submission_originality", {
|
197 |
"submission": submission,
|
198 |
"reference_sources": reference_sources
|
199 |
})
|
200 |
-
|
201 |
-
# ------------ External Integrations ------------
|
202 |
-
|
203 |
-
def lms_sync_grades(self, lms_type: str, api_url: str, api_key: str,
|
204 |
-
course_id: str, assignment_id: str,
|
205 |
-
grades: List[Dict[str, Any]]) -> Dict[str, Any]:
|
206 |
-
"""Sync grades with a Learning Management System"""
|
207 |
-
return self._call_tool("lms_sync_grades", {
|
208 |
-
"lms_type": lms_type,
|
209 |
-
"api_url": api_url,
|
210 |
-
"api_key": api_key,
|
211 |
-
"course_id": course_id,
|
212 |
-
"assignment_id": assignment_id,
|
213 |
-
"grades": grades
|
214 |
-
})
|
215 |
-
|
216 |
-
def oer_search(self, repository_url: str, query: str,
|
217 |
-
subject: Optional[str] = None, grade_level: Optional[str] = None,
|
218 |
-
api_key: Optional[str] = None) -> Dict[str, Any]:
|
219 |
-
"""Search for educational resources in OER repositories"""
|
220 |
-
params = {
|
221 |
-
"repository_url": repository_url,
|
222 |
-
"query": query
|
223 |
-
}
|
224 |
-
|
225 |
-
if subject:
|
226 |
-
params["subject"] = subject
|
227 |
-
|
228 |
-
if grade_level:
|
229 |
-
params["grade_level"] = grade_level
|
230 |
-
|
231 |
-
if api_key:
|
232 |
-
params["api_key"] = api_key
|
233 |
-
|
234 |
-
return self._call_tool("oer_search", params)
|
235 |
-
|
236 |
-
def schedule_tutoring_session(self, platform_url: str, client_id: str, client_secret: str,
|
237 |
-
student_id: str, subject: str, datetime_str: str) -> Dict[str, Any]:
|
238 |
-
"""Schedule a session with a real-time personalized tutoring platform"""
|
239 |
-
return self._call_tool("schedule_tutoring_session", {
|
240 |
-
"platform_url": platform_url,
|
241 |
-
"client_id": client_id,
|
242 |
-
"client_secret": client_secret,
|
243 |
-
"student_id": student_id,
|
244 |
-
"subject": subject,
|
245 |
-
"datetime_str": datetime_str
|
246 |
-
})
|
247 |
|
248 |
# Create a default client instance for easy import
|
249 |
client = TutorXClient()
|
|
|
190 |
return self._call_tool("get_student_analytics", {
|
191 |
"student_id": student_id,
|
192 |
"timeframe_days": timeframe_days
|
193 |
+
})
|
194 |
+
def check_submission_originality(self, submission: str, reference_sources: List[str]) -> Dict[str, Any]:
|
195 |
"""Check student submission for potential plagiarism"""
|
196 |
return self._call_tool("check_submission_originality", {
|
197 |
"submission": submission,
|
198 |
"reference_sources": reference_sources
|
199 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
|
201 |
# Create a default client instance for easy import
|
202 |
client = TutorXClient()
|
docs/api.md
DELETED
@@ -1,368 +0,0 @@
|
|
1 |
-
# TutorX-MCP API Documentation
|
2 |
-
|
3 |
-
This document provides comprehensive documentation for the TutorX-MCP API for developers who want to integrate with the system.
|
4 |
-
|
5 |
-
## API Overview
|
6 |
-
|
7 |
-
The TutorX-MCP server exposes a Model Context Protocol (MCP) API that allows clients to interact with various educational tools and resources. This API follows the standard MCP protocol as defined in [MCP Specification](https://github.com/anthropics/anthropic-tools/blob/main/mcp/README.md).
|
8 |
-
|
9 |
-
## Authentication
|
10 |
-
|
11 |
-
For production deployments, all API requests should include an API key in the `Authorization` header:
|
12 |
-
|
13 |
-
```
|
14 |
-
Authorization: Bearer your-api-key-here
|
15 |
-
```
|
16 |
-
|
17 |
-
## Base URL
|
18 |
-
|
19 |
-
Default: `http://localhost:8000`
|
20 |
-
|
21 |
-
For production: See your deployment configuration
|
22 |
-
|
23 |
-
## Tools API
|
24 |
-
|
25 |
-
Tools represent functionality that can be invoked by MCP clients. Each tool is accessed via:
|
26 |
-
|
27 |
-
```
|
28 |
-
POST /tools/{tool_name}
|
29 |
-
Content-Type: application/json
|
30 |
-
|
31 |
-
{
|
32 |
-
"param1": "value1",
|
33 |
-
"param2": "value2"
|
34 |
-
}
|
35 |
-
```
|
36 |
-
|
37 |
-
### Core Features
|
38 |
-
|
39 |
-
#### Adaptive Learning Engine
|
40 |
-
|
41 |
-
##### `assess_skill`
|
42 |
-
|
43 |
-
Assess a student's skill level on a specific concept.
|
44 |
-
|
45 |
-
**Request:**
|
46 |
-
```json
|
47 |
-
{
|
48 |
-
"student_id": "student123",
|
49 |
-
"concept_id": "math_algebra_basics"
|
50 |
-
}
|
51 |
-
```
|
52 |
-
|
53 |
-
**Response:**
|
54 |
-
```json
|
55 |
-
{
|
56 |
-
"student_id": "student123",
|
57 |
-
"concept_id": "math_algebra_basics",
|
58 |
-
"skill_level": 0.75,
|
59 |
-
"confidence": 0.85,
|
60 |
-
"recommendations": [
|
61 |
-
"Practice more complex problems",
|
62 |
-
"Review related concept: algebra_linear_equations"
|
63 |
-
],
|
64 |
-
"timestamp": "2025-06-07T10:30:45.123456"
|
65 |
-
}
|
66 |
-
```
|
67 |
-
|
68 |
-
##### `generate_quiz`
|
69 |
-
|
70 |
-
Generate a quiz based on specified concepts and difficulty.
|
71 |
-
|
72 |
-
**Request:**
|
73 |
-
```json
|
74 |
-
{
|
75 |
-
"concept_ids": ["math_algebra_basics", "math_algebra_linear_equations"],
|
76 |
-
"difficulty": 2
|
77 |
-
}
|
78 |
-
```
|
79 |
-
|
80 |
-
**Response:**
|
81 |
-
```json
|
82 |
-
{
|
83 |
-
"quiz_id": "q12345",
|
84 |
-
"concept_ids": ["math_algebra_basics", "math_algebra_linear_equations"],
|
85 |
-
"difficulty": 2,
|
86 |
-
"questions": [
|
87 |
-
{
|
88 |
-
"id": "q1",
|
89 |
-
"text": "Solve for x: 2x + 3 = 7",
|
90 |
-
"type": "algebraic_equation",
|
91 |
-
"answer": "x = 2",
|
92 |
-
"solution_steps": [
|
93 |
-
"2x + 3 = 7",
|
94 |
-
"2x = 7 - 3",
|
95 |
-
"2x = 4",
|
96 |
-
"x = 4/2 = 2"
|
97 |
-
]
|
98 |
-
}
|
99 |
-
]
|
100 |
-
}
|
101 |
-
```
|
102 |
-
|
103 |
-
#### Feedback System
|
104 |
-
|
105 |
-
##### `analyze_error_patterns`
|
106 |
-
|
107 |
-
Analyze common error patterns for a student on a specific concept.
|
108 |
-
|
109 |
-
**Request:**
|
110 |
-
```json
|
111 |
-
{
|
112 |
-
"student_id": "student123",
|
113 |
-
"concept_id": "math_algebra_basics"
|
114 |
-
}
|
115 |
-
```
|
116 |
-
|
117 |
-
**Response:**
|
118 |
-
```json
|
119 |
-
{
|
120 |
-
"student_id": "student123",
|
121 |
-
"concept_id": "math_algebra_basics",
|
122 |
-
"common_errors": [
|
123 |
-
{
|
124 |
-
"type": "sign_error",
|
125 |
-
"frequency": 0.65,
|
126 |
-
"example": "2x - 3 = 5 → 2x = 5 - 3 → 2x = 2 → x = 1 (should be x = 4)"
|
127 |
-
}
|
128 |
-
],
|
129 |
-
"recommendations": [
|
130 |
-
"Practice more sign manipulation problems"
|
131 |
-
]
|
132 |
-
}
|
133 |
-
```
|
134 |
-
|
135 |
-
### Advanced Features
|
136 |
-
|
137 |
-
#### Neurological Engagement Monitor
|
138 |
-
|
139 |
-
##### `analyze_cognitive_state`
|
140 |
-
|
141 |
-
Analyze EEG data to determine cognitive state.
|
142 |
-
|
143 |
-
**Request:**
|
144 |
-
```json
|
145 |
-
{
|
146 |
-
"eeg_data": {
|
147 |
-
"channels": [...],
|
148 |
-
"sampling_rate": 256,
|
149 |
-
"duration": 10.0
|
150 |
-
}
|
151 |
-
}
|
152 |
-
```
|
153 |
-
|
154 |
-
**Response:**
|
155 |
-
```json
|
156 |
-
{
|
157 |
-
"attention_level": 0.82,
|
158 |
-
"cognitive_load": 0.65,
|
159 |
-
"stress_level": 0.25,
|
160 |
-
"recommendations": [
|
161 |
-
"Student is engaged but approaching cognitive overload",
|
162 |
-
"Consider simplifying next problems slightly"
|
163 |
-
],
|
164 |
-
"timestamp": "2025-06-07T10:32:15.123456"
|
165 |
-
}
|
166 |
-
```
|
167 |
-
|
168 |
-
### External Integrations
|
169 |
-
|
170 |
-
#### Learning Management Systems
|
171 |
-
|
172 |
-
##### `lms_sync_grades`
|
173 |
-
|
174 |
-
Sync grades with a Learning Management System.
|
175 |
-
|
176 |
-
**Request:**
|
177 |
-
```json
|
178 |
-
{
|
179 |
-
"lms_type": "canvas",
|
180 |
-
"api_url": "https://canvas.example.com/api/v1",
|
181 |
-
"api_key": "your-api-key",
|
182 |
-
"course_id": "course123",
|
183 |
-
"assignment_id": "assign456",
|
184 |
-
"grades": [
|
185 |
-
{
|
186 |
-
"student_id": "student123",
|
187 |
-
"score": 85.5
|
188 |
-
}
|
189 |
-
]
|
190 |
-
}
|
191 |
-
```
|
192 |
-
|
193 |
-
**Response:**
|
194 |
-
```json
|
195 |
-
{
|
196 |
-
"success": true,
|
197 |
-
"timestamp": "2025-06-07T10:35:22.123456",
|
198 |
-
"message": "Grades successfully synced"
|
199 |
-
}
|
200 |
-
```
|
201 |
-
|
202 |
-
#### Open Educational Resources
|
203 |
-
|
204 |
-
##### `oer_search`
|
205 |
-
|
206 |
-
Search for educational resources in OER repositories.
|
207 |
-
|
208 |
-
**Request:**
|
209 |
-
```json
|
210 |
-
{
|
211 |
-
"repository_url": "https://oer.example.com/api",
|
212 |
-
"query": "linear equations",
|
213 |
-
"subject": "mathematics",
|
214 |
-
"grade_level": "8"
|
215 |
-
}
|
216 |
-
```
|
217 |
-
|
218 |
-
**Response:**
|
219 |
-
```json
|
220 |
-
{
|
221 |
-
"success": true,
|
222 |
-
"count": 2,
|
223 |
-
"results": [
|
224 |
-
{
|
225 |
-
"id": "resource123",
|
226 |
-
"title": "Introduction to Linear Equations",
|
227 |
-
"description": "A comprehensive guide to solving linear equations",
|
228 |
-
"url": "https://oer.example.com/resources/resource123",
|
229 |
-
"subject": "mathematics",
|
230 |
-
"grade_level": "8-9",
|
231 |
-
"license": "CC-BY"
|
232 |
-
}
|
233 |
-
],
|
234 |
-
"timestamp": "2025-06-07T10:36:12.123456"
|
235 |
-
}
|
236 |
-
```
|
237 |
-
|
238 |
-
#### Real-Time Personalized Tutoring
|
239 |
-
|
240 |
-
##### `schedule_tutoring_session`
|
241 |
-
|
242 |
-
Schedule a session with a real-time personalized tutoring platform.
|
243 |
-
|
244 |
-
**Request:**
|
245 |
-
```json
|
246 |
-
{
|
247 |
-
"platform_url": "https://tutoring.example.com/api",
|
248 |
-
"client_id": "your-client-id",
|
249 |
-
"client_secret": "your-client-secret",
|
250 |
-
"student_id": "student123",
|
251 |
-
"subject": "mathematics",
|
252 |
-
"datetime_str": "2025-06-10T15:00:00Z"
|
253 |
-
}
|
254 |
-
```
|
255 |
-
|
256 |
-
**Response:**
|
257 |
-
```json
|
258 |
-
{
|
259 |
-
"success": true,
|
260 |
-
"session_id": "session789",
|
261 |
-
"tutor": {
|
262 |
-
"id": "tutor456",
|
263 |
-
"name": "Dr. Jane Smith",
|
264 |
-
"rating": 4.9,
|
265 |
-
"specialization": "mathematics"
|
266 |
-
},
|
267 |
-
"datetime": "2025-06-10T15:00:00Z",
|
268 |
-
"join_url": "https://tutoring.example.com/session/session789",
|
269 |
-
"timestamp": "2025-06-07T10:37:45.123456"
|
270 |
-
}
|
271 |
-
```
|
272 |
-
|
273 |
-
## Resources API
|
274 |
-
|
275 |
-
Resources represent data that can be fetched by MCP clients. Each resource is accessed via:
|
276 |
-
|
277 |
-
```
|
278 |
-
GET /resources?uri={resource_uri}
|
279 |
-
Accept: application/json
|
280 |
-
```
|
281 |
-
|
282 |
-
### Available Resources
|
283 |
-
|
284 |
-
#### `concept-graph://`
|
285 |
-
|
286 |
-
Retrieves the full knowledge concept graph.
|
287 |
-
|
288 |
-
#### `learning-path://{student_id}`
|
289 |
-
|
290 |
-
Retrieves the personalized learning path for a student.
|
291 |
-
|
292 |
-
#### `curriculum-standards://{country_code}`
|
293 |
-
|
294 |
-
Retrieves curriculum standards for a specific country.
|
295 |
-
|
296 |
-
#### `student-dashboard://{student_id}`
|
297 |
-
|
298 |
-
Retrieves dashboard data for a specific student.
|
299 |
-
|
300 |
-
## Error Handling
|
301 |
-
|
302 |
-
API errors follow a standard format:
|
303 |
-
|
304 |
-
```json
|
305 |
-
{
|
306 |
-
"error": {
|
307 |
-
"code": "error_code",
|
308 |
-
"message": "Human-readable error message",
|
309 |
-
"details": {}
|
310 |
-
}
|
311 |
-
}
|
312 |
-
```
|
313 |
-
|
314 |
-
Common error codes:
|
315 |
-
- `invalid_request`: The request was malformed
|
316 |
-
- `authentication_error`: Authentication failed
|
317 |
-
- `not_found`: The requested resource does not exist
|
318 |
-
- `server_error`: Internal server error
|
319 |
-
|
320 |
-
## Rate Limiting
|
321 |
-
|
322 |
-
Production deployments implement rate limiting to prevent abuse. Clients should monitor the following headers:
|
323 |
-
|
324 |
-
- `X-RateLimit-Limit`: Maximum requests per hour
|
325 |
-
- `X-RateLimit-Remaining`: Remaining requests for the current hour
|
326 |
-
- `X-RateLimit-Reset`: Timestamp when the limit will reset
|
327 |
-
|
328 |
-
## SDK
|
329 |
-
|
330 |
-
For easier integration, we provide client SDKs in multiple languages:
|
331 |
-
|
332 |
-
- Python: `pip install tutorx-client`
|
333 |
-
- JavaScript: `npm install tutorx-client`
|
334 |
-
|
335 |
-
Example usage (Python):
|
336 |
-
|
337 |
-
```python
|
338 |
-
from tutorx_client import TutorXClient
|
339 |
-
|
340 |
-
client = TutorXClient("http://localhost:8000", api_key="your-api-key")
|
341 |
-
|
342 |
-
# Call a tool
|
343 |
-
result = client.assess_skill("student123", "math_algebra_basics")
|
344 |
-
print(result["skill_level"])
|
345 |
-
|
346 |
-
# Access a resource
|
347 |
-
concept_graph = client.get_concept_graph()
|
348 |
-
```
|
349 |
-
|
350 |
-
## Webhooks
|
351 |
-
|
352 |
-
For real-time updates, you can register webhook endpoints:
|
353 |
-
|
354 |
-
```
|
355 |
-
POST /webhooks/register
|
356 |
-
Content-Type: application/json
|
357 |
-
Authorization: Bearer your-api-key
|
358 |
-
|
359 |
-
{
|
360 |
-
"url": "https://your-app.example.com/webhook",
|
361 |
-
"events": ["assessment.completed", "badge.awarded"],
|
362 |
-
"secret": "your-webhook-secret"
|
363 |
-
}
|
364 |
-
```
|
365 |
-
|
366 |
-
## Support
|
367 |
-
|
368 |
-
For API support, contact us at [email protected]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/prd.md
CHANGED
@@ -51,7 +51,6 @@ To provide an adaptive, multi-modal, and collaborative AI tutoring platform acce
|
|
51 |
- **Feedback System**
|
52 |
- Contextual error analysis and suggestions
|
53 |
- Multimodal feedback (text, audio, visual)
|
54 |
-
- Emotional state recognition (via webcam/EEG)
|
55 |
|
56 |
## 3.2 Advanced Features
|
57 |
|
@@ -74,8 +73,6 @@ To provide an adaptive, multi-modal, and collaborative AI tutoring platform acce
|
|
74 |
- **Accessibility**
|
75 |
- Screen reader compatibility
|
76 |
- Text-to-speech and adjustable interface
|
77 |
-
- **Gamification**
|
78 |
-
- Badges, leaderboards, token-based rewards
|
79 |
|
80 |
---
|
81 |
|
@@ -85,18 +82,7 @@ To provide an adaptive, multi-modal, and collaborative AI tutoring platform acce
|
|
85 |
- **Gradio Interface:** User-friendly, customizable, and accessible
|
86 |
- **Microservices Architecture:** Modular design for scalability
|
87 |
- **Real-Time Data Processing:** Asynchronous task queues and caching
|
88 |
-
- **
|
89 |
-
- **Integration:** Supports external APIs, LMS, and educational tools
|
90 |
-
|
91 |
-
---
|
92 |
-
|
93 |
-
## 5. Non-Functional Requirements
|
94 |
-
|
95 |
-
- **Performance:** Supports 100+ concurrent users with <1s response time for core features
|
96 |
-
- **Security:** End-to-end encryption, role-based access control
|
97 |
-
- **Privacy:** Compliant with GDPR, COPPA, and FERPA
|
98 |
-
- **Scalability:** Horizontally scalable to support large institutions
|
99 |
-
- **Accessibility:** WCAG 2.1 AA compliant
|
100 |
|
101 |
---
|
102 |
|
@@ -115,7 +101,7 @@ To provide an adaptive, multi-modal, and collaborative AI tutoring platform acce
|
|
115 |
1. **Phase 1:** Core adaptive learning engine and MCP integration
|
116 |
2. **Phase 2:** Multi-modal interaction and collaborative tools
|
117 |
3. **Phase 3:** Advanced features (engagement monitor, lesson authoring)
|
118 |
-
4. **Phase 4:**
|
119 |
|
120 |
---
|
121 |
|
|
|
51 |
- **Feedback System**
|
52 |
- Contextual error analysis and suggestions
|
53 |
- Multimodal feedback (text, audio, visual)
|
|
|
54 |
|
55 |
## 3.2 Advanced Features
|
56 |
|
|
|
73 |
- **Accessibility**
|
74 |
- Screen reader compatibility
|
75 |
- Text-to-speech and adjustable interface
|
|
|
|
|
76 |
|
77 |
---
|
78 |
|
|
|
82 |
- **Gradio Interface:** User-friendly, customizable, and accessible
|
83 |
- **Microservices Architecture:** Modular design for scalability
|
84 |
- **Real-Time Data Processing:** Asynchronous task queues and caching
|
85 |
+
- **Local Access:** Browser-based access from local machine
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
---
|
88 |
|
|
|
101 |
1. **Phase 1:** Core adaptive learning engine and MCP integration
|
102 |
2. **Phase 2:** Multi-modal interaction and collaborative tools
|
103 |
3. **Phase 3:** Advanced features (engagement monitor, lesson authoring)
|
104 |
+
4. **Phase 4:** Analytics and performance monitoring
|
105 |
|
106 |
---
|
107 |
|
main.py
CHANGED
@@ -18,11 +18,6 @@ from utils.assessment import (
|
|
18 |
generate_performance_analytics,
|
19 |
detect_plagiarism
|
20 |
)
|
21 |
-
from utils.integrations import (
|
22 |
-
LMSIntegration,
|
23 |
-
OERIntegration,
|
24 |
-
RTPTIntegration
|
25 |
-
)
|
26 |
|
27 |
# Create the TutorX MCP server
|
28 |
mcp = FastMCP("TutorX")
|
@@ -581,124 +576,9 @@ def check_submission_originality(submission: str, reference_sources: List[str])
|
|
581 |
reference_sources: List of reference texts to check against
|
582 |
|
583 |
Returns:
|
584 |
-
Originality analysis
|
585 |
-
return detect_plagiarism(submission, reference_sources)
|
586 |
-
|
587 |
-
# ------------------ External Integrations ------------------
|
588 |
-
|
589 |
-
@mcp.tool()
|
590 |
-
def lms_sync_grades(lms_type: str, api_url: str, api_key: str,
|
591 |
-
course_id: str, assignment_id: str,
|
592 |
-
grades: List[Dict[str, Any]]) -> Dict[str, Any]:
|
593 |
-
"""
|
594 |
-
Sync grades with a Learning Management System
|
595 |
-
|
596 |
-
Args:
|
597 |
-
lms_type: Type of LMS ('canvas', 'moodle', 'blackboard')
|
598 |
-
api_url: URL for the LMS API
|
599 |
-
api_key: API key for authentication
|
600 |
-
course_id: ID of the course
|
601 |
-
assignment_id: ID of the assignment
|
602 |
-
grades: List of grade data to sync
|
603 |
-
|
604 |
-
Returns:
|
605 |
-
Status of the sync operation
|
606 |
"""
|
607 |
-
|
608 |
-
lms = LMSIntegration(lms_type, api_url, api_key)
|
609 |
-
success = lms.sync_grades(course_id, assignment_id, grades)
|
610 |
-
return {
|
611 |
-
"success": success,
|
612 |
-
"timestamp": datetime.now().isoformat(),
|
613 |
-
"message": "Grades successfully synced" if success else "Failed to sync grades"
|
614 |
-
}
|
615 |
-
except Exception as e:
|
616 |
-
return {
|
617 |
-
"success": False,
|
618 |
-
"error": str(e),
|
619 |
-
"timestamp": datetime.now().isoformat()
|
620 |
-
}
|
621 |
-
|
622 |
-
@mcp.tool()
|
623 |
-
def oer_search(repository_url: str, query: str,
|
624 |
-
subject: Optional[str] = None, grade_level: Optional[str] = None,
|
625 |
-
api_key: Optional[str] = None) -> Dict[str, Any]:
|
626 |
-
"""
|
627 |
-
Search for educational resources in OER repositories
|
628 |
-
|
629 |
-
Args:
|
630 |
-
repository_url: URL of the OER repository
|
631 |
-
query: Search query
|
632 |
-
subject: Optional subject filter
|
633 |
-
grade_level: Optional grade level filter
|
634 |
-
api_key: Optional API key if required
|
635 |
-
|
636 |
-
Returns:
|
637 |
-
List of matching resources
|
638 |
-
"""
|
639 |
-
try:
|
640 |
-
oer = OERIntegration(repository_url, api_key)
|
641 |
-
results = oer.search_resources(query, subject, grade_level)
|
642 |
-
return {
|
643 |
-
"success": True,
|
644 |
-
"count": len(results),
|
645 |
-
"results": results,
|
646 |
-
"timestamp": datetime.now().isoformat()
|
647 |
-
}
|
648 |
-
except Exception as e:
|
649 |
-
return {
|
650 |
-
"success": False,
|
651 |
-
"error": str(e),
|
652 |
-
"timestamp": datetime.now().isoformat()
|
653 |
-
}
|
654 |
-
|
655 |
-
@mcp.tool()
|
656 |
-
def schedule_tutoring_session(platform_url: str, client_id: str, client_secret: str,
|
657 |
-
student_id: str, subject: str, datetime_str: str) -> Dict[str, Any]:
|
658 |
-
"""
|
659 |
-
Schedule a session with a real-time personalized tutoring platform
|
660 |
-
|
661 |
-
Args:
|
662 |
-
platform_url: URL of the tutoring platform
|
663 |
-
client_id: OAuth client ID
|
664 |
-
client_secret: OAuth client secret
|
665 |
-
student_id: ID of the student
|
666 |
-
subject: Subject for tutoring
|
667 |
-
datetime_str: ISO format datetime for the session
|
668 |
-
|
669 |
-
Returns:
|
670 |
-
Session details
|
671 |
-
"""
|
672 |
-
try:
|
673 |
-
# Find an available tutor
|
674 |
-
rtpt = RTPTIntegration(platform_url, client_id, client_secret)
|
675 |
-
tutors = rtpt.get_available_tutors(subject, "intermediate")
|
676 |
-
|
677 |
-
if not tutors:
|
678 |
-
return {
|
679 |
-
"success": False,
|
680 |
-
"message": "No tutors available for this subject",
|
681 |
-
"timestamp": datetime.now().isoformat()
|
682 |
-
}
|
683 |
-
|
684 |
-
# Schedule with first available tutor
|
685 |
-
tutor_id = tutors[0]["id"]
|
686 |
-
session = rtpt.schedule_session(student_id, tutor_id, subject, datetime_str)
|
687 |
-
|
688 |
-
return {
|
689 |
-
"success": True,
|
690 |
-
"session_id": session.get("id"),
|
691 |
-
"tutor": session.get("tutor"),
|
692 |
-
"datetime": session.get("datetime"),
|
693 |
-
"join_url": session.get("join_url"),
|
694 |
-
"timestamp": datetime.now().isoformat()
|
695 |
-
}
|
696 |
-
except Exception as e:
|
697 |
-
return {
|
698 |
-
"success": False,
|
699 |
-
"error": str(e),
|
700 |
-
"timestamp": datetime.now().isoformat()
|
701 |
-
}
|
702 |
|
703 |
if __name__ == "__main__":
|
704 |
mcp.run()
|
|
|
18 |
generate_performance_analytics,
|
19 |
detect_plagiarism
|
20 |
)
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
# Create the TutorX MCP server
|
23 |
mcp = FastMCP("TutorX")
|
|
|
576 |
reference_sources: List of reference texts to check against
|
577 |
|
578 |
Returns:
|
579 |
+
Originality analysis
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
580 |
"""
|
581 |
+
return detect_plagiarism(submission, reference_sources)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
582 |
|
583 |
if __name__ == "__main__":
|
584 |
mcp.run()
|
utils/integrations.py
DELETED
@@ -1,251 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Integration utilities for connecting TutorX-MCP with external educational systems
|
3 |
-
"""
|
4 |
-
|
5 |
-
import requests
|
6 |
-
import json
|
7 |
-
import os
|
8 |
-
from typing import Dict, Any, List, Optional
|
9 |
-
import logging
|
10 |
-
|
11 |
-
logger = logging.getLogger(__name__)
|
12 |
-
|
13 |
-
class LMSIntegration:
|
14 |
-
"""Integration with Learning Management Systems (Canvas, Moodle, etc.)"""
|
15 |
-
|
16 |
-
def __init__(self, lms_type: str, api_url: str, api_key: str):
|
17 |
-
"""
|
18 |
-
Initialize LMS integration
|
19 |
-
|
20 |
-
Args:
|
21 |
-
lms_type: Type of LMS ('canvas', 'moodle', 'blackboard', etc.)
|
22 |
-
api_url: Base URL for LMS API
|
23 |
-
api_key: API key or token for authentication
|
24 |
-
"""
|
25 |
-
self.lms_type = lms_type.lower()
|
26 |
-
self.api_url = api_url.rstrip('/')
|
27 |
-
self.api_key = api_key
|
28 |
-
|
29 |
-
def get_courses(self) -> List[Dict[str, Any]]:
|
30 |
-
"""Get list of courses from LMS"""
|
31 |
-
if self.lms_type == 'canvas':
|
32 |
-
return self._canvas_get_courses()
|
33 |
-
elif self.lms_type == 'moodle':
|
34 |
-
return self._moodle_get_courses()
|
35 |
-
else:
|
36 |
-
raise ValueError(f"Unsupported LMS type: {self.lms_type}")
|
37 |
-
|
38 |
-
def _canvas_get_courses(self) -> List[Dict[str, Any]]:
|
39 |
-
"""Get courses from Canvas LMS"""
|
40 |
-
headers = {"Authorization": f"Bearer {self.api_key}"}
|
41 |
-
response = requests.get(f"{self.api_url}/courses", headers=headers)
|
42 |
-
response.raise_for_status()
|
43 |
-
return response.json()
|
44 |
-
|
45 |
-
def _moodle_get_courses(self) -> List[Dict[str, Any]]:
|
46 |
-
"""Get courses from Moodle"""
|
47 |
-
params = {
|
48 |
-
"wstoken": self.api_key,
|
49 |
-
"wsfunction": "core_course_get_courses",
|
50 |
-
"moodlewsrestformat": "json"
|
51 |
-
}
|
52 |
-
response = requests.get(f"{self.api_url}/webservice/rest/server.php", params=params)
|
53 |
-
response.raise_for_status()
|
54 |
-
return response.json()
|
55 |
-
|
56 |
-
def sync_grades(self, course_id: str, assignment_id: str, grades: List[Dict[str, Any]]) -> bool:
|
57 |
-
"""
|
58 |
-
Sync grades to LMS
|
59 |
-
|
60 |
-
Args:
|
61 |
-
course_id: ID of the course
|
62 |
-
assignment_id: ID of the assignment
|
63 |
-
grades: List of grade data to sync
|
64 |
-
|
65 |
-
Returns:
|
66 |
-
Success status
|
67 |
-
"""
|
68 |
-
try:
|
69 |
-
if self.lms_type == 'canvas':
|
70 |
-
return self._canvas_sync_grades(course_id, assignment_id, grades)
|
71 |
-
elif self.lms_type == 'moodle':
|
72 |
-
return self._moodle_sync_grades(course_id, assignment_id, grades)
|
73 |
-
else:
|
74 |
-
raise ValueError(f"Unsupported LMS type: {self.lms_type}")
|
75 |
-
except Exception as e:
|
76 |
-
logger.error(f"Error syncing grades: {e}")
|
77 |
-
return False
|
78 |
-
|
79 |
-
def _canvas_sync_grades(self, course_id: str, assignment_id: str, grades: List[Dict[str, Any]]) -> bool:
|
80 |
-
"""Sync grades to Canvas LMS"""
|
81 |
-
headers = {"Authorization": f"Bearer {self.api_key}"}
|
82 |
-
|
83 |
-
for grade in grades:
|
84 |
-
data = {
|
85 |
-
"submission": {
|
86 |
-
"posted_grade": grade["score"]
|
87 |
-
}
|
88 |
-
}
|
89 |
-
|
90 |
-
url = f"{self.api_url}/courses/{course_id}/assignments/{assignment_id}/submissions/{grade['student_id']}"
|
91 |
-
response = requests.put(url, json=data, headers=headers)
|
92 |
-
|
93 |
-
if response.status_code != 200:
|
94 |
-
logger.error(f"Failed to sync grade for student {grade['student_id']}: {response.text}")
|
95 |
-
return False
|
96 |
-
|
97 |
-
return True
|
98 |
-
|
99 |
-
def _moodle_sync_grades(self, course_id: str, assignment_id: str, grades: List[Dict[str, Any]]) -> bool:
|
100 |
-
"""Sync grades to Moodle"""
|
101 |
-
# Implementation specific to Moodle's API
|
102 |
-
# This would use the Moodle grade update API
|
103 |
-
return True # Placeholder
|
104 |
-
|
105 |
-
class OERIntegration:
|
106 |
-
"""Integration with Open Educational Resources repositories"""
|
107 |
-
|
108 |
-
def __init__(self, repository_url: str, api_key: Optional[str] = None):
|
109 |
-
"""
|
110 |
-
Initialize OER repository integration
|
111 |
-
|
112 |
-
Args:
|
113 |
-
repository_url: Base URL for OER repository API
|
114 |
-
api_key: Optional API key if required by the repository
|
115 |
-
"""
|
116 |
-
self.repository_url = repository_url.rstrip('/')
|
117 |
-
self.api_key = api_key
|
118 |
-
|
119 |
-
def search_resources(self, query: str, subject: Optional[str] = None,
|
120 |
-
grade_level: Optional[str] = None) -> List[Dict[str, Any]]:
|
121 |
-
"""
|
122 |
-
Search for educational resources
|
123 |
-
|
124 |
-
Args:
|
125 |
-
query: Search query
|
126 |
-
subject: Optional subject filter
|
127 |
-
grade_level: Optional grade level filter
|
128 |
-
|
129 |
-
Returns:
|
130 |
-
List of matching resources
|
131 |
-
"""
|
132 |
-
params = {"q": query}
|
133 |
-
|
134 |
-
if subject:
|
135 |
-
params["subject"] = subject
|
136 |
-
|
137 |
-
if grade_level:
|
138 |
-
params["grade"] = grade_level
|
139 |
-
|
140 |
-
headers = {}
|
141 |
-
if self.api_key:
|
142 |
-
headers["Authorization"] = f"Bearer {self.api_key}"
|
143 |
-
|
144 |
-
response = requests.get(f"{self.repository_url}/search", params=params, headers=headers)
|
145 |
-
response.raise_for_status()
|
146 |
-
|
147 |
-
return response.json().get("results", [])
|
148 |
-
|
149 |
-
def get_resource(self, resource_id: str) -> Dict[str, Any]:
|
150 |
-
"""
|
151 |
-
Get details for a specific resource
|
152 |
-
|
153 |
-
Args:
|
154 |
-
resource_id: ID of the resource to fetch
|
155 |
-
|
156 |
-
Returns:
|
157 |
-
Resource details
|
158 |
-
"""
|
159 |
-
headers = {}
|
160 |
-
if self.api_key:
|
161 |
-
headers["Authorization"] = f"Bearer {self.api_key}"
|
162 |
-
|
163 |
-
response = requests.get(f"{self.repository_url}/resources/{resource_id}", headers=headers)
|
164 |
-
response.raise_for_status()
|
165 |
-
|
166 |
-
return response.json()
|
167 |
-
|
168 |
-
|
169 |
-
class RTPTIntegration:
|
170 |
-
"""Integration with real-time personalized tutoring platforms"""
|
171 |
-
|
172 |
-
def __init__(self, platform_url: str, client_id: str, client_secret: str):
|
173 |
-
"""
|
174 |
-
Initialize RTPT integration
|
175 |
-
|
176 |
-
Args:
|
177 |
-
platform_url: Base URL for RTPT platform API
|
178 |
-
client_id: OAuth client ID
|
179 |
-
client_secret: OAuth client secret
|
180 |
-
"""
|
181 |
-
self.platform_url = platform_url.rstrip('/')
|
182 |
-
self.client_id = client_id
|
183 |
-
self.client_secret = client_secret
|
184 |
-
self._access_token = None
|
185 |
-
|
186 |
-
def _get_access_token(self) -> str:
|
187 |
-
"""Get OAuth access token"""
|
188 |
-
if self._access_token:
|
189 |
-
return self._access_token
|
190 |
-
|
191 |
-
data = {
|
192 |
-
"grant_type": "client_credentials",
|
193 |
-
"client_id": self.client_id,
|
194 |
-
"client_secret": self.client_secret
|
195 |
-
}
|
196 |
-
|
197 |
-
response = requests.post(f"{self.platform_url}/oauth/token", data=data)
|
198 |
-
response.raise_for_status()
|
199 |
-
|
200 |
-
token_data = response.json()
|
201 |
-
self._access_token = token_data["access_token"]
|
202 |
-
return self._access_token
|
203 |
-
|
204 |
-
def get_available_tutors(self, subject: str, level: str) -> List[Dict[str, Any]]:
|
205 |
-
"""
|
206 |
-
Get available tutors for a subject and level
|
207 |
-
|
208 |
-
Args:
|
209 |
-
subject: Academic subject
|
210 |
-
level: Academic level
|
211 |
-
|
212 |
-
Returns:
|
213 |
-
List of available tutors
|
214 |
-
"""
|
215 |
-
headers = {"Authorization": f"Bearer {self._get_access_token()}"}
|
216 |
-
params = {
|
217 |
-
"subject": subject,
|
218 |
-
"level": level
|
219 |
-
}
|
220 |
-
|
221 |
-
response = requests.get(f"{self.platform_url}/tutors/available", params=params, headers=headers)
|
222 |
-
response.raise_for_status()
|
223 |
-
|
224 |
-
return response.json()
|
225 |
-
|
226 |
-
def schedule_session(self, student_id: str, tutor_id: str,
|
227 |
-
subject: str, datetime_str: str) -> Dict[str, Any]:
|
228 |
-
"""
|
229 |
-
Schedule a tutoring session
|
230 |
-
|
231 |
-
Args:
|
232 |
-
student_id: ID of the student
|
233 |
-
tutor_id: ID of the tutor
|
234 |
-
subject: Subject for tutoring
|
235 |
-
datetime_str: ISO format datetime for the session
|
236 |
-
|
237 |
-
Returns:
|
238 |
-
Session details
|
239 |
-
"""
|
240 |
-
headers = {"Authorization": f"Bearer {self._get_access_token()}"}
|
241 |
-
data = {
|
242 |
-
"student_id": student_id,
|
243 |
-
"tutor_id": tutor_id,
|
244 |
-
"subject": subject,
|
245 |
-
"datetime": datetime_str
|
246 |
-
}
|
247 |
-
|
248 |
-
response = requests.post(f"{self.platform_url}/sessions", json=data, headers=headers)
|
249 |
-
response.raise_for_status()
|
250 |
-
|
251 |
-
return response.json()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|