shyamsridhar123 commited on
Commit
2cb386d
Β·
0 Parent(s):

Initial commit: Agentic Skill Builder for MCP Hackathon 2025

Browse files
.env ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ο»Ώ# Azure Cosmos DB Configuration
2
+ COSMOS_ENDPOINT=cosmosgremlinai.gremlin.cosmosdb.azure.com
3
+ COSMOS_USERNAME=/dbs/graphdb/colls/ProductsGraph
4
+ COSMOS_PASSWORD=vIoky0D389svaUPQSMqUxf4O3eqQpyOTHWt88izYnVDyLz05q6O7UVEYx7v2pGFBQFGuRWyP6ztlACDbbsMTSw==
5
+ COSMOS_DATABASE=graphdb
6
+ COSMOS_GRAPH=ProductsGraph
7
+
8
+ # Azure OpenAI Configuration
9
+ AZURE_OPENAI_ENDPOINT="https://aihubeastus26267492086.openai.azure.com/"
10
+ AZURE_OPENAI_KEY="2oQRUb4k4Ws3oqaOJyC4ybWCPT3nmTpmIlAXvGzYRvWYFfCDsE8GJQQJ99BEACHYHv6XJ3w3AAAAACOGH87p"
11
+ AZURE_OPENAI_API_VERSION="2024-12-01-preview"
12
+
13
+ # LLM Model Configuration
14
+ AZURE_OPENAI_LLM_DEPLOYMENT="gpt-4.1"
15
+ AZURE_OPENAI_LLM_MODEL="gpt-4.1"
16
+
17
+ # Embeddings Model Configuration
18
+ AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT="text-embedding-3-small"
19
+ AZURE_OPENAI_EMBEDDINGS_MODEL="text-embedding-3-small"
20
+
21
+ # Graphiti Configuration
22
+ GRAPHITI_GROUP_NAME="manybirds_graph"
.gitignore ADDED
File without changes
.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
3
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
4
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
5
+ WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
6
+ ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
7
+ MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
8
+ h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
9
+ 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
10
+ A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
11
+ T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
12
+ B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
13
+ B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
14
+ KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
15
+ OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
16
+ jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
17
+ qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
18
+ rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
19
+ HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
20
+ hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
21
+ ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
22
+ 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
23
+ NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
24
+ ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
25
+ TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
26
+ jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
27
+ oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
28
+ 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
29
+ mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
30
+ emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
31
+ -----END CERTIFICATE-----
PRD.md ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ # Product Requirements Document (PRD)
4
+
5
+ ## Product Name
6
+
7
+ **Agentic Skill Builder**
8
+
9
+ ## Purpose
10
+
11
+ Agentic Skill Builder is an AI-powered microlearning platform designed to help users learn new skills through bite-sized lessons and adaptive quizzes. The platform leverages Azure OpenAI for content generation, Gradio for user interaction, and Model Context Protocol (MCP) for agent interoperability.
12
+
13
+ ---
14
+
15
+ ## 1. Objectives
16
+
17
+ - **Deliver Personalized Microlearning:** Provide users with concise, high-quality lessons and adaptive quizzes tailored to their chosen skill.
18
+ - **Showcase Agentic Workflows:** Demonstrate how multiple AI agents (lesson generator, quiz generator, progress tracker) can collaborate to enhance learning.
19
+ - **Enable Interoperability via MCP:** Allow external agents and applications to interact with the learning modules and user progress through MCP endpoints.
20
+ - **Offer a Polished, User-Friendly Interface:** Use Gradio to deliver an intuitive, engaging, and accessible experience.
21
+
22
+ ---
23
+
24
+ ## 2. Target Users
25
+
26
+ - **Lifelong Learners:** Individuals seeking to acquire or reinforce skills in short, focused sessions.
27
+ - **Hackathon Participants:** Developers and researchers interested in agentic workflows and MCP integration.
28
+ - **Educational Institutions:** Teachers and trainers looking for AI-driven microlearning tools.
29
+ - **Integration Developers:** Teams building apps that could benefit from plug-and-play learning modules.
30
+
31
+ ---
32
+
33
+ ## 3. Features \& Requirements
34
+
35
+ ### 3.1 Core Features
36
+
37
+ #### 3.1.1 Skill Selection
38
+
39
+ - Users can select from a list of predefined skills (e.g., Python, Spanish, Public Speaking) or enter a custom skill/topic.
40
+
41
+
42
+ #### 3.1.2 Micro-Lesson Delivery
43
+
44
+ - For the chosen skill, the system generates and presents a concise, focused lesson (text, optionally with links to videos or code snippets).
45
+ - Lessons are generated dynamically using Azure OpenAI.
46
+
47
+
48
+ #### 3.1.3 Adaptive Quiz
49
+
50
+ - After each lesson, users receive a short quiz (e.g., multiple choice, fill-in-the-blank) tailored to the lesson content.
51
+ - The quiz adapts in difficulty based on user performance over time.
52
+
53
+
54
+ #### 3.1.4 Progress Tracking
55
+
56
+ - The system tracks user progress (e.g., lessons completed, quiz accuracy, streaks).
57
+ - Progress is displayed visually (e.g., progress bars, charts).
58
+
59
+
60
+ #### 3.1.5 Recommendations
61
+
62
+ - Based on performance, the system recommends the next lesson, a review session, or an increased difficulty level.
63
+
64
+
65
+ ### 3.2 Agentic Architecture
66
+
67
+ - **Lesson Agent:** Generates concise lessons for the selected skill.
68
+ - **Quiz Agent:** Creates contextually relevant quizzes based on the lesson.
69
+ - **Progress Agent:** Monitors and updates user progress, provides feedback, and recommends next steps.
70
+ - **Orchestrator:** Coordinates the flow between agents and the user interface.
71
+
72
+
73
+ ### 3.3 MCP Integration
74
+
75
+ - Expose endpoints for:
76
+ - Fetching the next lesson for a user/skill.
77
+ - Retrieving user progress data.
78
+ - Submitting quiz results.
79
+ - Ensure endpoints are documented and compatible with the Model Context Protocol.
80
+
81
+
82
+ ### 3.4 User Interface
83
+
84
+ - **Built with Gradio:**
85
+ - Step-by-step workflow: Skill selection β†’ Lesson β†’ Quiz β†’ Feedback/Progress.
86
+ - Clean, accessible design with clear navigation.
87
+ - Responsive for desktop and mobile.
88
+
89
+ ---
90
+
91
+ ## 4. Non-Functional Requirements
92
+
93
+ - **Performance:** Lessons and quizzes should be generated in under 5 seconds.
94
+ - **Scalability:** Support at least 100 concurrent users for demo purposes.
95
+ - **Security:** User data (progress, answers) is stored securely and not shared without consent.
96
+ - **Accessibility:** UI should be usable with screen readers and keyboard navigation.
97
+ - **Reliability:** System should handle API failures gracefully and provide user-friendly error messages.
98
+
99
+ ---
100
+
101
+ ## 5. Optional \& Stretch Features
102
+
103
+ - **Speech-to-Text Input:** For language practice, allow users to answer quizzes verbally.
104
+ - **Leaderboard:** Display top learners (opt-in).
105
+ - **Daily Reminders:** Send notifications or emails to encourage regular learning.
106
+ - **Custom Content Upload:** Allow educators to add their own lesson modules.
107
+ - **Multi-modal Lessons:** Incorporate images, audio, or video if supported by Azure OpenAI.
108
+
109
+ ---
110
+
111
+ ## 6. Technical Stack
112
+
113
+ - **Backend:** Azure OpenAI (GPT-3.5, GPT-4, or GPT-4o)
114
+ - **Frontend:** Gradio (Python)
115
+ - **MCP Integration:** Gradio MCP server functionality
116
+ - **Data Storage:** In-memory or lightweight database (for hackathon demo)
117
+ - **Deployment:** Hugging Face Spaces or Azure App Service
118
+
119
+ ---
120
+
121
+ ## 7. Success Metrics
122
+
123
+ - **User Engagement:** Number of lessons/quizzes completed per user.
124
+ - **Learning Outcomes:** Improvement in quiz scores over sessions.
125
+ - **MCP Usage:** Number of successful external calls to MCP endpoints.
126
+ - **User Satisfaction:** Positive feedback from hackathon judges and users.
127
+
128
+ ---
129
+
130
+ ## 8. Risks \& Mitigations
131
+
132
+ | Risk | Mitigation |
133
+ | :-- | :-- |
134
+ | Slow response from Azure OpenAI | Cache common lessons/quizzes, optimize prompts |
135
+ | User data loss (demo) | Regular backups, clear communication |
136
+ | MCP integration complexity | Use official Gradio MCP templates and docs |
137
+ | Overly generic lessons/quizzes | Refine prompts, add manual review if possible |
138
+
139
+
140
+ ---
141
+
142
+ ## 9. Milestones \& Timeline
143
+
144
+ | Milestone | Target Date |
145
+ | :-- | :-- |
146
+ | Project setup \& Azure OpenAI config | Day 1 |
147
+ | Core agent logic implemented | Day 2 |
148
+ | Gradio UI complete | Day 3 |
149
+ | MCP endpoints exposed \& tested | Day 4 |
150
+ | Polish, optional features, testing | Day 5 |
151
+ | Submission \& documentation | Day 6 |
152
+
153
+
154
+ ---
155
+
156
+ ## 10. Appendix
157
+
158
+ - **References:**
159
+ - [Gradio Documentation](https://www.gradio.app/)
160
+ - [Azure OpenAI Documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/)
161
+ - [Model Context Protocol](https://modelcontextprotocol.io/)
162
+ - **Contact:**
163
+ - Hackathon team email/slack/discord
164
+
165
+ ---
166
+
167
+ **This PRD is designed for clarity, feasibility, and alignment with hackathon goals. Let me know if you need a version tailored for a specific audience (e.g., business, technical, or educational) or want to add/remove features!**
168
+
README.md ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Agentic Skill Builder - MCP Hackathon 2025
3
+ emoji: πŸš€
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 4.44.0
8
+ app_file: space_app.py
9
+ pinned: false
10
+ license: mit
11
+ tags:
12
+ - mcp-server-track
13
+ - agents
14
+ - education
15
+ - microlearning
16
+ - azure-openai
17
+ - model-context-protocol
18
+ short_description: AI-powered microlearning platform with MCP integration for the Gradio Agents & MCP Hackathon 2025
19
+ ---
20
+
21
+ # πŸš€ Agentic Skill Builder
22
+
23
+ **Track:** mcp-server-track
24
+
25
+ An AI-powered microlearning platform that leverages Azure OpenAI, Gradio, and Model Context Protocol (MCP) to deliver personalized bite-sized lessons and adaptive quizzes.
26
+
27
+ πŸŽ“ **Submitted for the Gradio Agents & MCP Hackathon 2025** πŸš€
28
+
29
+ ## 🎬 Demo Video
30
+
31
+ **MCP Server in Action:** [Demo Video Link](https://your-demo-video-link.com)
32
+
33
+ *Note: The video demonstrates the MCP server endpoints being used by various MCP clients, showcasing the seamless integration between the Gradio interface and Model Context Protocol functionality.*
34
+
35
+ ## πŸ† Hackathon Highlights
36
+
37
+ This submission demonstrates several key innovations for the **Gradio Agents & MCP Hackathon 2025**:
38
+
39
+ ### πŸ€– **Track 1: MCP Server/Tool**
40
+ - βœ… **Dual-Purpose Application**: Single app serving both Gradio interface AND MCP server
41
+ - βœ… **Full MCP Protocol Implementation**: Complete endpoints for lesson generation, progress tracking, and quiz submission
42
+ - βœ… **External Agent Integration**: Ready for use by Claude Desktop, Cursor, or any MCP client
43
+
44
+ ### 🧠 **Agentic Architecture Innovation**
45
+ - **πŸŽ“ Lesson Agent**: AI-powered content generation with Azure OpenAI
46
+ - **πŸ§ͺ Quiz Agent**: Adaptive quiz creation based on lesson content and user performance
47
+ - **πŸ“Š Progress Agent**: Smart difficulty adjustment and learning recommendations
48
+ - **🎯 Orchestrator**: Seamless coordination between all agents and user interactions
49
+
50
+ ### πŸ”— **MCP Endpoints Showcase**
51
+ - `GET /mcp/skills` - Discover available learning skills
52
+ - `POST /mcp/lesson/generate` - Generate personalized micro-lessons
53
+ - `GET /mcp/progress/{user_id}` - Access detailed learning analytics
54
+ - `POST /mcp/quiz/submit` - Submit and score quiz attempts
55
+
56
+ ### πŸ’‘ **Unique Features**
57
+ - **Microlearning Focus**: 3-5 minute bite-sized lessons perfect for busy learners
58
+ - **Adaptive Difficulty**: AI automatically adjusts based on quiz performance
59
+ - **Any Skill Learning**: Works for both predefined and custom skills
60
+ - **Real-time Analytics**: Live progress tracking and personalized recommendations
61
+
62
+ ## ✨ Features
63
+
64
+ - 🎯 **Skill Selection**: Choose from predefined skills or enter custom topics
65
+ - πŸ“š **AI-Generated Micro-Lessons**: Concise, focused lessons (3-5 minutes)
66
+ - 🧠 **Adaptive Quizzes**: Smart quizzes that adjust difficulty based on performance
67
+ - πŸ“Š **Progress Tracking**: Visual progress monitoring and analytics
68
+ - πŸ€– **Agentic Architecture**: Multiple specialized AI agents working together
69
+ - πŸ”— **MCP Integration**: Model Context Protocol endpoints for external integration
70
+ - 🎨 **Modern UI**: Clean, responsive Gradio interface
71
+
72
+ ## πŸ—οΈ Architecture
73
+
74
+ The application uses an agentic architecture with specialized AI agents:
75
+
76
+ - **Lesson Agent**: Generates personalized micro-lessons
77
+ - **Quiz Agent**: Creates adaptive quizzes based on lesson content
78
+ - **Progress Agent**: Tracks learning progress and provides recommendations
79
+ - **Orchestrator**: Coordinates agent interactions and user flow
80
+
81
+ ## πŸš€ Quick Start
82
+
83
+ ### Prerequisites
84
+
85
+ - **Python 3.10.16** installed
86
+ - Azure OpenAI subscription with API key
87
+ - Access to GPT-4 model deployment
88
+
89
+ ### Installation
90
+
91
+ 1. **Clone and navigate to the project:**
92
+ ```powershell
93
+ cd c:\Users\shyamsridhar\code\hf-hackathon
94
+ ```
95
+
96
+ 2. **Create and activate a virtual environment:**
97
+ ```powershell
98
+ python -m venv .venv
99
+ .venv\Scripts\Activate
100
+ ```
101
+ *(On macOS/Linux, use `source .venv/bin/activate`)*
102
+
103
+ 3. **Install dependencies:**
104
+ ```powershell
105
+ pip install -r requirements.txt
106
+ ```
107
+
108
+ 4. **Configure environment variables:**
109
+ - Your `.env` file is already configured with Azure OpenAI credentials
110
+ - Verify the credentials are correct and models are deployed
111
+
112
+ 5. **Run the application:**
113
+ ```powershell
114
+ python run.py
115
+ ```
116
+
117
+ Choose from three options:
118
+ - **Option 1**: Gradio App only (recommended for demo)
119
+ - **Option 2**: MCP Server only
120
+ - **Option 3**: Both services
121
+
122
+ ## 🎯 Usage
123
+
124
+ ### Learning Flow
125
+
126
+ 1. **Select a Skill**: Choose from predefined skills or enter a custom topic
127
+ 2. **Read the Lesson**: Engage with AI-generated micro-content
128
+ 3. **Take the Quiz**: Test your understanding with adaptive questions
129
+ 4. **View Results**: Get detailed feedback and progress updates
130
+ 5. **Continue Learning**: Follow AI recommendations for next steps
131
+
132
+ ### Available Skills
133
+
134
+ - Python Programming
135
+ - Spanish Language
136
+ - Public Speaking
137
+ - Data Science
138
+ - Machine Learning
139
+ - JavaScript
140
+ - Project Management
141
+ - Digital Marketing
142
+ - Creative Writing
143
+ - Photography
144
+
145
+ *Plus any custom skill you can imagine!*
146
+
147
+ ## πŸ”— MCP Endpoints
148
+
149
+ The application exposes Model Context Protocol endpoints at `http://localhost:8000`:
150
+
151
+ - `GET /skills` - List available skills
152
+ - `POST /lesson/generate` - Generate lesson for a skill
153
+ - `GET /progress/{user_id}` - Get user progress data
154
+ - `POST /quiz/submit` - Submit quiz results
155
+ - `POST /quiz/generate` - Generate quiz for a lesson
156
+
157
+ ### API Documentation
158
+
159
+ Visit `http://localhost:8000/docs` for interactive API documentation.
160
+
161
+ ## πŸ“Š Progress Dashboard
162
+
163
+ Track your learning journey with:
164
+
165
+ - **Lessons Completed**: Number of lessons finished per skill
166
+ - **Quiz Performance**: Average scores and improvement trends
167
+ - **Difficulty Progression**: Automatic difficulty adjustment
168
+ - **Learning Streaks**: Consistent learning tracking
169
+ - **AI Recommendations**: Personalized next steps
170
+
171
+ ## πŸ”§ Configuration
172
+
173
+ ### Environment Variables
174
+
175
+ The `.env` file contains your Azure OpenAI configuration:
176
+
177
+ ```properties
178
+ # Azure OpenAI Configuration
179
+ AZURE_OPENAI_ENDPOINT="your-endpoint"
180
+ AZURE_OPENAI_KEY="your-api-key"
181
+ AZURE_OPENAI_API_VERSION="2024-12-01-preview"
182
+ AZURE_OPENAI_LLM_DEPLOYMENT="gpt-4.1"
183
+ AZURE_OPENAI_LLM_MODEL="gpt-4.1"
184
+ ```
185
+
186
+ ### Optional Settings
187
+
188
+ You can add these optional environment variables:
189
+
190
+ ```properties
191
+ DEBUG=false
192
+ LOG_LEVEL=INFO
193
+ GRADIO_PORT=7860
194
+ MCP_PORT=8000
195
+ MAX_QUIZ_QUESTIONS=5
196
+ DEFAULT_LESSON_DURATION=5
197
+ ```
198
+
199
+ ## πŸ§ͺ Development
200
+
201
+ ### Running in Development Mode
202
+
203
+ ```powershell
204
+ # Install development dependencies
205
+ pip install -r requirements.txt
206
+
207
+ # Run with auto-reload
208
+ python app.py
209
+ ```
210
+
211
+ ### Testing MCP Endpoints
212
+
213
+ ```bash
214
+ # Test lesson generation
215
+ curl -X POST "http://localhost:8000/lesson/generate" \
216
+ -H "Content-Type: application/json" \
217
+ -d '{"skill": "Python Programming", "user_id": "test_user"}'
218
+
219
+ # Get user progress
220
+ curl "http://localhost:8000/progress/test_user?skill=Python%20Programming"
221
+ ```
222
+
223
+ ## πŸ“± Deployment
224
+
225
+ ### Local Deployment
226
+
227
+ ```powershell
228
+ python run.py
229
+ ```
230
+
231
+ ### Hugging Face Spaces
232
+
233
+ 1. Create a new Space on Hugging Face
234
+ 2. Upload your code
235
+ 3. Set environment variables in Space settings
236
+ 4. The app will auto-deploy
237
+
238
+ ### Azure App Service
239
+
240
+ 1. Create an Azure App Service
241
+ 2. Deploy using Git or ZIP
242
+ 3. Configure environment variables
243
+ 4. Set startup command: `python app.py`
244
+
245
+ ## πŸ” Troubleshooting
246
+
247
+ ### Common Issues
248
+
249
+ 1. **Azure OpenAI Connection Error**
250
+ - Verify your endpoint URL and API key
251
+ - Check if your model deployment is active
252
+ - Ensure you have sufficient quota
253
+
254
+ 2. **Module Import Errors**
255
+ - Activate your virtual environment
256
+ - Install requirements: `pip install -r requirements.txt`
257
+
258
+ 3. **Port Already in Use**
259
+ - Change ports in environment variables
260
+ - Kill existing processes: `netstat -ano | findstr :7860`
261
+
262
+ ### Logs
263
+
264
+ Check application logs in `agentic_skill_builder.log` for detailed error information.
265
+
266
+ ## 🀝 Contributing
267
+
268
+ 1. Fork the repository
269
+ 2. Create a feature branch
270
+ 3. Make your changes
271
+ 4. Test thoroughly
272
+ 5. Submit a pull request
273
+
274
+ ## πŸ“„ License
275
+
276
+ This project is part of a hackathon submission. See the full requirements in `i dont want the code but a detailed prd document.md`.
277
+
278
+ ## πŸ† Hackathon Features
279
+
280
+ This implementation demonstrates:
281
+
282
+ - βœ… **Agentic Workflows**: Multiple AI agents collaborating
283
+ - βœ… **Azure OpenAI Integration**: Modern SDK usage with best practices
284
+ - βœ… **Adaptive Learning**: Smart difficulty adjustment
285
+ - βœ… **Modern UI**: Gradio-based responsive interface
286
+ - βœ… **MCP Protocol**: External agent integration capability
287
+ - βœ… **Progress Analytics**: Comprehensive learning tracking
288
+ - βœ… **Error Handling**: Robust error management and fallbacks
289
+
290
+ ## πŸ“ž Support
291
+
292
+ For issues or questions:
293
+ 1. Check the troubleshooting section
294
+ 2. Review the logs in `agentic_skill_builder.log`
295
+ 3. Verify your Azure OpenAI configuration
296
+ 4. Ensure all dependencies are installed correctly
297
+
298
+ ---
299
+
300
+ **Happy Learning! πŸŽ“**
README_spaces.md ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ title: Agentic Skill Builder - MCP Hackathon 2025
2
+ emoji: πŸš€
3
+ colorFrom: blue
4
+ colorTo: purple
5
+ sdk: gradio
6
+ sdk_version: 4.44.0
7
+ app_file: space_app.py
8
+ pinned: false
9
+ license: mit
10
+ tags:
11
+ - mcp-server-track
12
+ - agents
13
+ - education
14
+ - microlearning
15
+ - azure-openai
16
+ - model-context-protocol
17
+ short_description: AI-powered microlearning platform with MCP integration for the Gradio Agents & MCP Hackathon 2025
__pycache__/app.cpython-310.pyc ADDED
Binary file (20.7 kB). View file
 
__pycache__/mcp_server.cpython-310.pyc ADDED
Binary file (6.7 kB). View file
 
__pycache__/space_app.cpython-310.pyc ADDED
Binary file (15.8 kB). View file
 
app.py ADDED
@@ -0,0 +1,647 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import asyncio
4
+ from datetime import datetime
5
+ from typing import Dict, List, Optional, Tuple
6
+ from dataclasses import dataclass, asdict
7
+ import logging
8
+
9
+ from dotenv import load_dotenv
10
+ import gradio as gr
11
+ from openai import AzureOpenAI
12
+ import pandas as pd
13
+
14
+ # Configure logging
15
+ logging.basicConfig(level=logging.INFO)
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # Load environment variables
19
+ load_dotenv()
20
+
21
+ # Azure OpenAI client configuration
22
+ client = AzureOpenAI(
23
+ azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT", "").replace('"', ''),
24
+ api_key=os.getenv("AZURE_OPENAI_KEY", "").replace('"', ''),
25
+ api_version=os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview").replace('"', ''),
26
+ )
27
+
28
+ # Model configurations
29
+ LLM_DEPLOYMENT = os.getenv("AZURE_OPENAI_LLM_DEPLOYMENT", "gpt-4.1").replace('"', '')
30
+ LLM_MODEL = os.getenv("AZURE_OPENAI_LLM_MODEL", "gpt-4.1").replace('"', '')
31
+
32
+ @dataclass
33
+ class UserProgress:
34
+ """Data class to track user learning progress"""
35
+ user_id: str
36
+ skill: str
37
+ lessons_completed: int = 0
38
+ quiz_scores: List[float] = None
39
+ current_difficulty: str = "beginner"
40
+ streak_days: int = 0
41
+ total_time_spent: int = 0 # minutes
42
+ last_activity: str = ""
43
+
44
+ def __post_init__(self):
45
+ if self.quiz_scores is None:
46
+ self.quiz_scores = []
47
+
48
+ def get_average_score(self) -> float:
49
+ """Calculate average quiz score"""
50
+ return sum(self.quiz_scores) / len(self.quiz_scores) if self.quiz_scores else 0.0
51
+
52
+ def add_quiz_score(self, score: float):
53
+ """Add a new quiz score and update difficulty if needed"""
54
+ self.quiz_scores.append(score)
55
+ # Adaptive difficulty adjustment
56
+ avg_score = self.get_average_score()
57
+ if avg_score >= 0.8 and len(self.quiz_scores) >= 3:
58
+ if self.current_difficulty == "beginner":
59
+ self.current_difficulty = "intermediate"
60
+ elif self.current_difficulty == "intermediate":
61
+ self.current_difficulty = "advanced"
62
+ elif avg_score < 0.6 and len(self.quiz_scores) >= 3:
63
+ if self.current_difficulty == "advanced":
64
+ self.current_difficulty = "intermediate"
65
+ elif self.current_difficulty == "intermediate":
66
+ self.current_difficulty = "beginner"
67
+
68
+ @dataclass
69
+ class Lesson:
70
+ """Data class for lesson content"""
71
+ title: str
72
+ content: str
73
+ skill: str
74
+ difficulty: str
75
+ duration_minutes: int
76
+ key_concepts: List[str]
77
+
78
+ @dataclass
79
+ class Quiz:
80
+ """Data class for quiz content"""
81
+ questions: List[Dict]
82
+ skill: str
83
+ difficulty: str
84
+ lesson_title: str
85
+
86
+ class LessonAgent:
87
+ """Agent responsible for generating personalized micro-lessons"""
88
+
89
+ def __init__(self, client: AzureOpenAI):
90
+ self.client = client
91
+ self.model = LLM_DEPLOYMENT
92
+
93
+ async def generate_lesson(self, skill: str, difficulty: str = "beginner",
94
+ previous_lessons: List[str] = None) -> Lesson:
95
+ """Generate a personalized micro-lesson"""
96
+ try:
97
+ previous_context = ""
98
+ if previous_lessons:
99
+ previous_context = f"\nPrevious lessons covered: {', '.join(previous_lessons[-3:])}"
100
+
101
+ prompt = f"""
102
+ Create a concise, engaging micro-lesson for the skill: {skill}
103
+ Difficulty level: {difficulty}
104
+ {previous_context}
105
+
106
+ Requirements:
107
+ - Lesson should be 3-5 minutes to read
108
+ - Include practical examples
109
+ - Focus on one key concept
110
+ - Make it actionable
111
+ - Include 3-5 key takeaways
112
+
113
+ Format your response as JSON with these fields:
114
+ {{
115
+ "title": "Lesson title",
116
+ "content": "Main lesson content (200-400 words)",
117
+ "duration_minutes": 4,
118
+ "key_concepts": ["concept1", "concept2", "concept3"]
119
+ }}
120
+ """
121
+
122
+ response = self.client.chat.completions.create(
123
+ model=self.model,
124
+ messages=[
125
+ {"role": "system", "content": "You are an expert educator creating micro-lessons. Always respond with valid JSON."},
126
+ {"role": "user", "content": prompt}
127
+ ],
128
+ temperature=0.7,
129
+ max_tokens=1000
130
+ )
131
+
132
+ lesson_data = json.loads(response.choices[0].message.content)
133
+
134
+ return Lesson(
135
+ title=lesson_data["title"],
136
+ content=lesson_data["content"],
137
+ skill=skill,
138
+ difficulty=difficulty,
139
+ duration_minutes=lesson_data["duration_minutes"],
140
+ key_concepts=lesson_data["key_concepts"]
141
+ )
142
+
143
+ except Exception as e:
144
+ logger.error(f"Error generating lesson: {e}")
145
+ # Fallback lesson
146
+ return Lesson(
147
+ title=f"Introduction to {skill}",
148
+ content=f"Let's start learning about {skill}. This is a fundamental skill that can help you grow professionally and personally.",
149
+ skill=skill,
150
+ difficulty=difficulty,
151
+ duration_minutes=3,
152
+ key_concepts=["basics", "fundamentals", "getting started"]
153
+ )
154
+
155
+ class QuizAgent:
156
+ """Agent responsible for generating adaptive quizzes"""
157
+
158
+ def __init__(self, client: AzureOpenAI):
159
+ self.client = client
160
+ self.model = LLM_DEPLOYMENT
161
+
162
+ async def generate_quiz(self, lesson: Lesson, user_progress: UserProgress) -> Quiz:
163
+ """Generate an adaptive quiz based on the lesson content"""
164
+ try:
165
+ avg_score = user_progress.get_average_score()
166
+
167
+ prompt = f"""
168
+ Create a quiz for this lesson:
169
+ Title: {lesson.title}
170
+ Content: {lesson.content}
171
+ Key concepts: {', '.join(lesson.key_concepts)}
172
+
173
+ User's average score: {avg_score:.1f}
174
+ Current difficulty: {lesson.difficulty}
175
+
176
+ Create 3-5 questions that test understanding of the lesson.
177
+ Mix question types: multiple choice, true/false, and short answer.
178
+
179
+ Format as JSON:
180
+ {{
181
+ "questions": [
182
+ {{
183
+ "type": "multiple_choice",
184
+ "question": "Question text?",
185
+ "options": ["A", "B", "C", "D"],
186
+ "correct_answer": "A",
187
+ "explanation": "Why this is correct"
188
+ }},
189
+ {{
190
+ "type": "true_false",
191
+ "question": "Statement to evaluate",
192
+ "correct_answer": true,
193
+ "explanation": "Explanation"
194
+ }}
195
+ ]
196
+ }}
197
+ """
198
+
199
+ response = self.client.chat.completions.create(
200
+ model=self.model,
201
+ messages=[
202
+ {"role": "system", "content": "You are a quiz expert. Always respond with valid JSON."},
203
+ {"role": "user", "content": prompt}
204
+ ],
205
+ temperature=0.7,
206
+ max_tokens=1200
207
+ )
208
+
209
+ quiz_data = json.loads(response.choices[0].message.content)
210
+
211
+ return Quiz(
212
+ questions=quiz_data["questions"],
213
+ skill=lesson.skill,
214
+ difficulty=lesson.difficulty,
215
+ lesson_title=lesson.title
216
+ )
217
+
218
+ except Exception as e:
219
+ logger.error(f"Error generating quiz: {e}")
220
+ # Fallback quiz
221
+ return Quiz(
222
+ questions=[{
223
+ "type": "multiple_choice",
224
+ "question": f"What is the main topic of this lesson about {lesson.skill}?",
225
+ "options": [lesson.skill, "Something else", "Not sure", "All of the above"],
226
+ "correct_answer": lesson.skill,
227
+ "explanation": f"This lesson focuses on {lesson.skill}"
228
+ }],
229
+ skill=lesson.skill,
230
+ difficulty=lesson.difficulty,
231
+ lesson_title=lesson.title
232
+ )
233
+
234
+ class ProgressAgent:
235
+ """Agent responsible for tracking progress and making recommendations"""
236
+
237
+ def __init__(self):
238
+ self.user_data: Dict[str, UserProgress] = {}
239
+
240
+ def get_user_progress(self, user_id: str, skill: str) -> UserProgress:
241
+ """Get or create user progress tracking"""
242
+ key = f"{user_id}_{skill}"
243
+ if key not in self.user_data:
244
+ self.user_data[key] = UserProgress(user_id=user_id, skill=skill)
245
+ return self.user_data[key]
246
+
247
+ def update_progress(self, user_id: str, skill: str, lesson_completed: bool = False,
248
+ quiz_score: float = None) -> UserProgress:
249
+ """Update user progress after lesson/quiz completion"""
250
+ progress = self.get_user_progress(user_id, skill)
251
+
252
+ if lesson_completed:
253
+ progress.lessons_completed += 1
254
+ progress.last_activity = datetime.now().strftime("%Y-%m-%d %H:%M")
255
+
256
+ if quiz_score is not None:
257
+ progress.add_quiz_score(quiz_score)
258
+
259
+ return progress
260
+
261
+ def get_recommendation(self, progress: UserProgress) -> str:
262
+ """Generate learning recommendations based on progress"""
263
+ avg_score = progress.get_average_score()
264
+
265
+ if progress.lessons_completed == 0:
266
+ return "🎯 Ready to start your learning journey! Begin with your first lesson."
267
+ elif avg_score >= 0.8:
268
+ return f"🌟 Excellent work! You're mastering {progress.skill}. Ready for the next challenge?"
269
+ elif avg_score >= 0.6:
270
+ return f"πŸ“ˆ Good progress! Keep practicing {progress.skill} to build confidence."
271
+ else:
272
+ return f"πŸ’ͺ Don't give up! Review the concepts and try again. Practice makes perfect!"
273
+
274
+ class AgenticSkillBuilder:
275
+ """Main orchestrator for the agentic skill building platform"""
276
+
277
+ def __init__(self):
278
+ self.lesson_agent = LessonAgent(client)
279
+ self.quiz_agent = QuizAgent(client)
280
+ self.progress_agent = ProgressAgent()
281
+ self.current_lesson: Optional[Lesson] = None
282
+ self.current_quiz: Optional[Quiz] = None
283
+ self.current_user = "demo_user" # In a real app, this would be from authentication
284
+
285
+ # Predefined skills
286
+ self.predefined_skills = [
287
+ "Python Programming", "Spanish Language", "Public Speaking",
288
+ "Data Science", "Machine Learning", "JavaScript", "Project Management",
289
+ "Digital Marketing", "Creative Writing", "Photography"
290
+ ]
291
+
292
+ async def start_lesson(self, skill: str) -> Tuple[str, str, str]:
293
+ """Start a new lesson for the selected skill"""
294
+ try:
295
+ progress = self.progress_agent.get_user_progress(self.current_user, skill)
296
+
297
+ # Get list of previous lesson titles for context
298
+ previous_lessons = [] # In a real app, you'd store this
299
+
300
+ self.current_lesson = await self.lesson_agent.generate_lesson(
301
+ skill, progress.current_difficulty, previous_lessons
302
+ )
303
+
304
+ lesson_content = f"""
305
+ # πŸ“š {self.current_lesson.title}
306
+
307
+ **Skill:** {self.current_lesson.skill} | **Level:** {self.current_lesson.difficulty.title()} | **Duration:** ~{self.current_lesson.duration_minutes} min
308
+
309
+ {self.current_lesson.content}
310
+
311
+ ### πŸ”‘ Key Concepts:
312
+ {chr(10).join([f"β€’ {concept}" for concept in self.current_lesson.key_concepts])}
313
+ """
314
+
315
+ return lesson_content, "βœ… Complete Lesson", ""
316
+
317
+ except Exception as e:
318
+ logger.error(f"Error starting lesson: {e}")
319
+ return f"❌ Error generating lesson: {str(e)}", "Try Again", ""
320
+
321
+ async def complete_lesson_and_start_quiz(self) -> Tuple[str, str, str]:
322
+ """Mark lesson as complete and start the quiz"""
323
+ if not self.current_lesson:
324
+ return "⚠️ No active lesson to complete.", "", ""
325
+
326
+ try:
327
+ # Update progress
328
+ progress = self.progress_agent.update_progress(
329
+ self.current_user, self.current_lesson.skill, lesson_completed=True
330
+ )
331
+
332
+ # Generate quiz
333
+ self.current_quiz = await self.quiz_agent.generate_quiz(self.current_lesson, progress)
334
+
335
+ quiz_content = f"""
336
+ # 🧠 Quiz: {self.current_lesson.title}
337
+
338
+ Test your understanding of the lesson. Answer all questions to see your results!
339
+
340
+ """
341
+
342
+ # Add questions to the content
343
+ for i, q in enumerate(self.current_quiz.questions, 1):
344
+ quiz_content += f"\n**Question {i}:** {q['question']}\n"
345
+ if q['type'] == 'multiple_choice':
346
+ quiz_content += f"Options: {', '.join(q['options'])}\n"
347
+ elif q['type'] == 'true_false':
348
+ quiz_content += "Answer: True or False\n"
349
+
350
+ return quiz_content, "πŸ“ Submit Quiz", ""
351
+
352
+ except Exception as e:
353
+ logger.error(f"Error generating quiz: {e}")
354
+ return f"❌ Error generating quiz: {str(e)}", "", ""
355
+
356
+ def submit_quiz(self, *answers) -> Tuple[str, str, str]:
357
+ """Process quiz submission and show results"""
358
+ if not self.current_quiz:
359
+ return "⚠️ No active quiz to submit.", "", ""
360
+
361
+ try:
362
+ correct_answers = 0
363
+ total_questions = len(self.current_quiz.questions)
364
+ results = []
365
+
366
+ for i, (question, answer) in enumerate(zip(self.current_quiz.questions, answers)):
367
+ if answer is None or answer == "":
368
+ continue
369
+
370
+ is_correct = False
371
+ correct_answer = question['correct_answer']
372
+
373
+ if question['type'] == 'multiple_choice':
374
+ is_correct = answer.strip().upper() == str(correct_answer).upper()
375
+ elif question['type'] == 'true_false':
376
+ is_correct = answer.lower() == str(correct_answer).lower()
377
+
378
+ if is_correct:
379
+ correct_answers += 1
380
+
381
+ results.append({
382
+ 'question': question['question'],
383
+ 'your_answer': answer,
384
+ 'correct_answer': correct_answer,
385
+ 'is_correct': is_correct,
386
+ 'explanation': question.get('explanation', '')
387
+ })
388
+
389
+ score = correct_answers / total_questions if total_questions > 0 else 0
390
+
391
+ # Update progress with quiz score
392
+ progress = self.progress_agent.update_progress(
393
+ self.current_user, self.current_lesson.skill, quiz_score=score
394
+ )
395
+
396
+ # Generate results content
397
+ results_content = f"""
398
+ # 🎯 Quiz Results
399
+
400
+ **Score:** {correct_answers}/{total_questions} ({score:.1%})
401
+
402
+ **Performance:** {'🌟 Excellent!' if score >= 0.8 else 'πŸ‘ Good work!' if score >= 0.6 else 'πŸ’ͺ Keep practicing!'}
403
+
404
+ ### Detailed Results:
405
+ """
406
+
407
+ for i, result in enumerate(results, 1):
408
+ status = "βœ…" if result['is_correct'] else "❌"
409
+ results_content += f"""
410
+ **Q{i}:** {result['question']}
411
+ {status} Your answer: {result['your_answer']}
412
+ Correct answer: {result['correct_answer']}
413
+ {result['explanation']}
414
+
415
+ """
416
+
417
+ # Add progress and recommendations
418
+ recommendation = self.progress_agent.get_recommendation(progress)
419
+
420
+ results_content += f"""
421
+ ### πŸ“Š Your Progress
422
+ - **Lessons completed:** {progress.lessons_completed}
423
+ - **Average score:** {progress.get_average_score():.1%}
424
+ - **Current level:** {progress.current_difficulty.title()}
425
+
426
+ ### 🎯 Recommendation
427
+ {recommendation}
428
+ """
429
+
430
+ return results_content, "πŸ”„ Start New Lesson", ""
431
+
432
+ except Exception as e:
433
+ logger.error(f"Error processing quiz: {e}")
434
+ return f"❌ Error processing quiz: {str(e)}", "", ""
435
+
436
+ # Initialize the main application
437
+ app = AgenticSkillBuilder()
438
+
439
+ def create_interface():
440
+ """Create the Gradio interface"""
441
+
442
+ with gr.Blocks(
443
+ title="Agentic Skill Builder",
444
+ theme=gr.themes.Soft(),
445
+ css="""
446
+ .gradio-container {
447
+ max-width: 800px !important;
448
+ margin: auto !important;
449
+ }
450
+ """
451
+ ) as demo:
452
+
453
+ # Header
454
+ gr.Markdown("""
455
+ # πŸš€ Agentic Skill Builder
456
+ ### AI-Powered Microlearning Platform
457
+
458
+ Learn new skills through bite-sized lessons and adaptive quizzes powered by Azure OpenAI!
459
+ """)
460
+
461
+ # State variables
462
+ current_skill = gr.State("")
463
+ with gr.Tab("🎯 Start Learning"):
464
+ gr.Markdown("### Choose a skill to begin your microlearning journey")
465
+
466
+ with gr.Row():
467
+ with gr.Column():
468
+ skill_dropdown = gr.Dropdown(
469
+ choices=app.predefined_skills,
470
+ label="πŸ“š Select a Skill",
471
+ info="Choose from popular skills..."
472
+ )
473
+ custom_skill = gr.Textbox(
474
+ label="✍️ Or enter a custom skill",
475
+ info="e.g., Cooking, Guitar, Time Management..."
476
+ )
477
+
478
+ start_btn = gr.Button("πŸš€ Start Learning", variant="primary", size="lg")
479
+
480
+ # Lesson content area
481
+ lesson_output = gr.Markdown(visible=False)
482
+ lesson_btn = gr.Button("Complete Lesson", visible=False)
483
+
484
+ # Quiz area
485
+ quiz_output = gr.Markdown(visible=False)
486
+
487
+ # Dynamic quiz inputs (will be created based on quiz content)
488
+ quiz_inputs = []
489
+ for i in range(5): # Max 5 questions
490
+ quiz_inputs.append(gr.Textbox(label=f"Answer {i+1}", visible=False))
491
+
492
+ quiz_submit_btn = gr.Button("Submit Quiz", visible=False)
493
+
494
+ # Results area
495
+ results_output = gr.Markdown(visible=False)
496
+ restart_btn = gr.Button("Start New Lesson", visible=False)
497
+
498
+ with gr.Tab("πŸ“Š Progress Dashboard"):
499
+ gr.Markdown("### Your Learning Analytics")
500
+
501
+ progress_display = gr.Markdown("""
502
+ **Welcome to your progress dashboard!**
503
+
504
+ Complete some lessons to see your learning analytics here.
505
+ """)
506
+
507
+ refresh_progress_btn = gr.Button("πŸ”„ Refresh Progress")
508
+
509
+ with gr.Tab("πŸ”— MCP Endpoints"):
510
+ gr.Markdown("""
511
+ ### Model Context Protocol Integration
512
+
513
+ This application exposes MCP endpoints for integration with external agents:
514
+
515
+ - **GET /lesson/{skill}** - Fetch next lesson for a skill
516
+ - **GET /progress/{user_id}** - Get user progress data
517
+ - **POST /quiz/submit** - Submit quiz results
518
+
519
+ *Coming soon: Full MCP server implementation*
520
+ """)
521
+ # Event handlers
522
+ async def handle_start_learning(skill_choice, custom_skill_input):
523
+ skill = custom_skill_input.strip() if custom_skill_input.strip() else skill_choice
524
+ if not skill:
525
+ return [
526
+ gr.update(value="⚠️ Please select or enter a skill to continue."),
527
+ gr.update(visible=False),
528
+ gr.update(visible=False),
529
+ skill
530
+ ] + [gr.update(visible=False, value="") for _ in range(5)]
531
+
532
+ lesson_content, btn_text, _ = await app.start_lesson(skill)
533
+
534
+ return [
535
+ gr.update(value=lesson_content),
536
+ gr.update(value=btn_text, visible=True),
537
+ gr.update(visible=False),
538
+ skill
539
+ ] + [gr.update(visible=False, value="") for _ in range(5)]
540
+
541
+ async def handle_complete_lesson():
542
+ quiz_content, btn_text, _ = await app.complete_lesson_and_start_quiz()
543
+
544
+ # Show quiz inputs based on number of questions
545
+ quiz_updates = []
546
+ if app.current_quiz:
547
+ for i, question in enumerate(app.current_quiz.questions):
548
+ if i < len(quiz_inputs):
549
+ label = f"Q{i+1}: {question['question'][:50]}..."
550
+ quiz_updates.append(gr.update(label=label, visible=True))
551
+ else:
552
+ quiz_updates.append(gr.update(visible=False))
553
+ # Hide remaining inputs
554
+ for i in range(len(app.current_quiz.questions), len(quiz_inputs)):
555
+ quiz_updates.append(gr.update(visible=False))
556
+ else:
557
+ quiz_updates = [gr.update(visible=False) for _ in range(len(quiz_inputs))]
558
+
559
+ return [
560
+ gr.update(visible=False),
561
+ gr.update(value=quiz_content, visible=True),
562
+ gr.update(value=btn_text, visible=True),
563
+ gr.update(visible=False)
564
+ ] + quiz_updates
565
+
566
+ def handle_submit_quiz(*answers):
567
+ # Filter out None values and empty strings
568
+ valid_answers = [ans for ans in answers if ans is not None and ans != ""]
569
+
570
+ results_content, btn_text, _ = app.submit_quiz(*valid_answers)
571
+
572
+ return [
573
+ gr.update(visible=False),
574
+ gr.update(value=results_content, visible=True),
575
+ gr.update(value=btn_text, visible=True),
576
+ gr.update(visible=False)
577
+ ] + [gr.update(visible=False) for _ in range(len(quiz_inputs))]
578
+
579
+ def handle_restart():
580
+ return [
581
+ gr.update(visible=False),
582
+ gr.update(visible=False),
583
+ gr.update(visible=False),
584
+ gr.update(visible=False),
585
+ gr.update(visible=False),
586
+ ""
587
+ ] + [gr.update(visible=False, value="") for _ in range(len(quiz_inputs))]
588
+
589
+ def update_progress_display():
590
+ if not app.progress_agent.user_data:
591
+ return "**No learning data yet.** Complete some lessons to see your progress!"
592
+
593
+ progress_content = "# πŸ“Š Your Learning Progress\n\n"
594
+
595
+ for key, progress in app.progress_agent.user_data.items():
596
+ progress_content += f"""
597
+ **Skill:** {progress.skill}
598
+ - Lessons completed: {progress.lessons_completed}
599
+ - Average quiz score: {progress.get_average_score():.1%}
600
+ - Current difficulty: {progress.current_difficulty.title()}
601
+ - Last activity: {progress.last_activity or 'Never'}
602
+
603
+ """
604
+ return progress_content
605
+
606
+ # Wire up the events
607
+ start_btn.click(
608
+ handle_start_learning,
609
+ inputs=[skill_dropdown, custom_skill],
610
+ outputs=[lesson_output, lesson_btn, quiz_output, current_skill] + quiz_inputs[:5]
611
+ )
612
+
613
+ lesson_btn.click(
614
+ handle_complete_lesson,
615
+ outputs=[lesson_btn, quiz_output, quiz_submit_btn, results_output] + quiz_inputs
616
+ )
617
+
618
+ quiz_submit_btn.click(
619
+ handle_submit_quiz,
620
+ inputs=quiz_inputs,
621
+ outputs=[quiz_submit_btn, results_output, restart_btn, quiz_output] + quiz_inputs
622
+ )
623
+
624
+ restart_btn.click(
625
+ handle_restart,
626
+ outputs=[lesson_output, quiz_output, results_output, lesson_btn, restart_btn, current_skill] + quiz_inputs
627
+ )
628
+
629
+ refresh_progress_btn.click(
630
+ update_progress_display,
631
+ outputs=[progress_display]
632
+ )
633
+
634
+ return demo
635
+
636
+ def main():
637
+ """Main application entry point"""
638
+ demo = create_interface()
639
+ demo.launch(
640
+ server_name="0.0.0.0",
641
+ server_port=7860,
642
+ share=False,
643
+ show_error=True
644
+ )
645
+
646
+ if __name__ == "__main__":
647
+ main()
config.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Configuration module for Agentic Skill Builder
3
+ Handles environment variables, logging, and application settings
4
+ """
5
+
6
+ import os
7
+ import logging
8
+ from typing import Optional
9
+ from dataclasses import dataclass
10
+
11
+ @dataclass
12
+ class AzureOpenAIConfig:
13
+ """Configuration for Azure OpenAI service"""
14
+ endpoint: str
15
+ api_key: str
16
+ api_version: str
17
+ llm_deployment: str
18
+ llm_model: str
19
+ embeddings_deployment: str
20
+ embeddings_model: str
21
+
22
+ @classmethod
23
+ def from_env(cls) -> 'AzureOpenAIConfig':
24
+ """Create configuration from environment variables"""
25
+ return cls(
26
+ endpoint=os.getenv("AZURE_OPENAI_ENDPOINT", "").replace('"', ''),
27
+ api_key=os.getenv("AZURE_OPENAI_KEY", "").replace('"', ''),
28
+ api_version=os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview").replace('"', ''),
29
+ llm_deployment=os.getenv("AZURE_OPENAI_LLM_DEPLOYMENT", "gpt-4.1").replace('"', ''),
30
+ llm_model=os.getenv("AZURE_OPENAI_LLM_MODEL", "gpt-4.1").replace('"', ''),
31
+ embeddings_deployment=os.getenv("AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT", "text-embedding-3-small").replace('"', ''),
32
+ embeddings_model=os.getenv("AZURE_OPENAI_EMBEDDINGS_MODEL", "text-embedding-3-small").replace('"', '')
33
+ )
34
+
35
+ def validate(self) -> bool:
36
+ """Validate that all required settings are present"""
37
+ required_fields = [self.endpoint, self.api_key, self.llm_deployment]
38
+ return all(field.strip() for field in required_fields)
39
+
40
+ @dataclass
41
+ class AppConfig:
42
+ """Main application configuration"""
43
+ debug: bool = False
44
+ log_level: str = "INFO"
45
+ gradio_port: int = 7860
46
+ mcp_port: int = 8000
47
+ max_quiz_questions: int = 5
48
+ default_lesson_duration: int = 5
49
+ azure_openai: Optional[AzureOpenAIConfig] = None
50
+
51
+ @classmethod
52
+ def from_env(cls) -> 'AppConfig':
53
+ """Create configuration from environment variables"""
54
+ return cls(
55
+ debug=os.getenv("DEBUG", "false").lower() == "true",
56
+ log_level=os.getenv("LOG_LEVEL", "INFO").upper(),
57
+ gradio_port=int(os.getenv("GRADIO_PORT", "7860")),
58
+ mcp_port=int(os.getenv("MCP_PORT", "8000")),
59
+ max_quiz_questions=int(os.getenv("MAX_QUIZ_QUESTIONS", "5")),
60
+ default_lesson_duration=int(os.getenv("DEFAULT_LESSON_DURATION", "5")),
61
+ azure_openai=AzureOpenAIConfig.from_env()
62
+ )
63
+
64
+ def setup_logging(config: AppConfig):
65
+ """Setup application logging"""
66
+ logging.basicConfig(
67
+ level=getattr(logging, config.log_level),
68
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
69
+ handlers=[
70
+ logging.StreamHandler(),
71
+ logging.FileHandler('agentic_skill_builder.log')
72
+ ]
73
+ )
74
+
75
+ def get_config() -> AppConfig:
76
+ """Get application configuration"""
77
+ config = AppConfig.from_env()
78
+
79
+ # Validate Azure OpenAI configuration
80
+ if not config.azure_openai or not config.azure_openai.validate():
81
+ raise ValueError(
82
+ "Azure OpenAI configuration is incomplete. "
83
+ "Please check your .env file for AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_KEY, and AZURE_OPENAI_LLM_DEPLOYMENT"
84
+ )
85
+
86
+ return config
demo_video_script.md ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🎬 Demo Video Script - Agentic Skill Builder MCP Server
2
+
3
+ ## Video Duration: 3-5 minutes
4
+ ## Target Audience: Hackathon judges and MCP developers
5
+
6
+ ---
7
+
8
+ ## 🎯 **Opening (0:00 - 0:30)**
9
+
10
+ **Visual:** Screen showing the Gradio interface running on localhost:7860
11
+ **Narration:**
12
+ > "Welcome to the Agentic Skill Builder - our submission for the Gradio Agents & MCP Hackathon 2025, Track 1: MCP Server/Tool. This is a unique AI-powered microlearning platform that serves both as a beautiful Gradio interface AND a fully functional MCP server."
13
+
14
+ ---
15
+
16
+ ## πŸ”— **MCP Server Demonstration (0:30 - 2:00)**
17
+
18
+ ### Part 1: Server Status & Endpoints (0:30 - 1:00)
19
+ **Visual:** Browser showing http://localhost:8001/
20
+ **Narration:**
21
+ > "First, let me show you our MCP server running on port 8001. This endpoint provides metadata about our hackathon submission."
22
+
23
+ **Action:** Show JSON response with hackathon information
24
+
25
+ **Visual:** Terminal/Postman showing MCP endpoints
26
+ **Narration:**
27
+ > "Our MCP server exposes four key endpoints:
28
+ > - GET /mcp/skills - Lists available learning skills
29
+ > - POST /mcp/lesson/generate - Creates personalized lessons
30
+ > - GET /mcp/progress/{user_id} - Tracks learning progress
31
+ > - POST /mcp/quiz/submit - Processes quiz submissions"
32
+
33
+ ### Part 2: Live MCP Endpoint Testing (1:00 - 2:00)
34
+ **Visual:** Testing each MCP endpoint with curl or PowerShell
35
+ **Narration:**
36
+ > "Let me demonstrate these endpoints in action. First, getting available skills..."
37
+
38
+ **Action:** Show GET /mcp/skills response
39
+ ```powershell
40
+ curl http://localhost:8001/mcp/skills
41
+ ```
42
+ **Expected Response:**
43
+ ```json
44
+ {
45
+ "predefined_skills": ["Python Programming", "Spanish Language", "Public Speaking", "Data Science", "Machine Learning", "JavaScript", "Project Management", "Digital Marketing", "Creative Writing", "Photography"]
46
+ }
47
+ ```
48
+
49
+ > "Now generating a personalized lesson for Python Programming..."
50
+
51
+ **Action:** Show POST /mcp/lesson/generate with request body and response
52
+ ```powershell
53
+ curl -X POST http://localhost:8001/mcp/lesson/generate `
54
+ -H "Content-Type: application/json" `
55
+ -d '{
56
+ "skill": "Python Programming",
57
+ "level": "beginner",
58
+ "user_context": "I want to learn Python for data analysis"
59
+ }'
60
+ ```
61
+ **Expected Response:**
62
+ ```json
63
+ {
64
+ "lesson_id": "lesson_12345",
65
+ "skill": "Python Programming",
66
+ "title": "Introduction to Python for Data Analysis",
67
+ "content": "Python is a powerful programming language...",
68
+ "difficulty": "beginner",
69
+ "estimated_time": "15 minutes",
70
+ "mcp_server": "Agentic Skill Builder"
71
+ }
72
+ ```
73
+
74
+ > "Let's check user progress to see learning analytics..."
75
+
76
+ **Action:** Show GET /mcp/progress/demo_user response
77
+ ```powershell
78
+ curl http://localhost:8001/mcp/progress/demo_user
79
+ ```
80
+ **Expected Response:**
81
+ ```json
82
+ {
83
+ "user_id": "demo_user",
84
+ "skills_progress": {
85
+ "Python Programming": {
86
+ "lessons_completed": 2,
87
+ "quiz_scores": [85, 92],
88
+ "current_level": "intermediate"
89
+ }
90
+ },
91
+ "total_skills_learning": 1,
92
+ "mcp_server": "Agentic Skill Builder",
93
+ "timestamp": "2025-06-07T04:48:36.691517"
94
+ }
95
+ ```
96
+
97
+ > "Finally, let's submit a quiz answer to show the interactive capabilities..."
98
+
99
+ **Action:** Show POST /mcp/quiz/submit with request body and response
100
+ ```powershell
101
+ curl -X POST http://localhost:8001/mcp/quiz/submit `
102
+ -H "Content-Type: application/json" `
103
+ -d '{
104
+ "user_id": "demo_user",
105
+ "quiz_id": "quiz_python_001",
106
+ "answers": ["list", "dictionary", "tuple"],
107
+ "skill": "Python Programming"
108
+ }'
109
+ ```
110
+ **Expected Response:**
111
+ ```json
112
+ {
113
+ "quiz_id": "quiz_python_001",
114
+ "user_id": "demo_user",
115
+ "score": 85,
116
+ "feedback": "Great job! You correctly identified Python data structures.",
117
+ "passed": true,
118
+ "mcp_server": "Agentic Skill Builder"
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## 🎨 **Gradio Interface Demo (2:00 - 3:30)**
125
+
126
+ ### Part 1: Learning Flow (2:00 - 3:00)
127
+ **Visual:** Gradio interface at localhost:7860
128
+ **Narration:**
129
+ > "Now let's see the beautiful Gradio interface in action. The same AI agents that power our MCP endpoints create this seamless learning experience."
130
+
131
+ **Action:**
132
+ 1. Select "Data Science" skill
133
+ 2. Click "Start Learning"
134
+ 3. Show generated lesson content
135
+ 4. Complete lesson and start quiz
136
+ 5. Answer quiz questions
137
+ 6. Show results and progress
138
+
139
+ ### Part 2: MCP Testing Interface (3:00 - 3:30)
140
+ **Visual:** Built-in MCP endpoint testing section in Gradio
141
+ **Narration:**
142
+ > "What makes this special is that we've built MCP endpoint testing directly into our Gradio interface. You can test all our MCP endpoints without leaving the app."
143
+
144
+ **Action:** Show the MCP endpoint testing interface working
145
+
146
+ ---
147
+
148
+ ## πŸ† **Hackathon Highlights (3:30 - 4:30)**
149
+
150
+ **Visual:** Split screen showing both Gradio UI and MCP endpoints
151
+ **Narration:**
152
+ > "This submission perfectly demonstrates the agentic architecture we've built:
153
+ > - Three specialized AI agents working together
154
+ > - Lesson Agent generates personalized content
155
+ > - Quiz Agent creates adaptive assessments
156
+ > - Progress Agent tracks learning analytics
157
+ > - All coordinated by our main orchestrator"
158
+
159
+ **Visual:** Show the architecture diagram or code structure
160
+ **Narration:**
161
+ > "The same agents power both the beautiful user interface AND the MCP protocol endpoints, making our platform ready for integration with Claude Desktop, Cursor, or any MCP client."
162
+
163
+ ---
164
+
165
+ ## πŸš€ **Call to Action (4:30 - 5:00)**
166
+
167
+ **Visual:** README.md showing deployment instructions
168
+ **Narration:**
169
+ > "You can deploy this immediately to Hugging Face Spaces using our space_app.py file, or run it locally following our comprehensive documentation. This represents the future of AI-powered education - agentic, interoperable, and ready for the Model Context Protocol ecosystem."
170
+
171
+ **Visual:** Final shot of both servers running simultaneously
172
+ **Narration:**
173
+ > "Thank you for watching our Agentic Skill Builder demo. We're excited to contribute to the MCP ecosystem and the future of AI agents working together!"
174
+
175
+ ---
176
+
177
+ ## πŸ“ **Recording Checklist**
178
+
179
+ ### Before Recording:
180
+ - [ ] Ensure both servers are running (Gradio on 7860, MCP on 8001)
181
+ - [ ] Prepare browser tabs for all endpoints
182
+ - [ ] Have curl commands or Postman collection ready
183
+ - [ ] Test the complete learning flow works
184
+ - [ ] Check audio/screen recording quality
185
+
186
+ ### During Recording:
187
+ - [ ] Speak clearly and at moderate pace
188
+ - [ ] Show actual JSON responses from MCP endpoints
189
+ - [ ] Demonstrate real-time lesson generation
190
+ - [ ] Highlight the dual-purpose architecture
191
+ - [ ] Keep within 5-minute time limit
192
+
193
+ ### After Recording:
194
+ - [ ] Upload to YouTube/Vimeo
195
+ - [ ] Update README.md with video link
196
+ - [ ] Add video link to HF Spaces README
197
+ - [ ] Verify video is publicly accessible
198
+
199
+ ---
200
+
201
+ ## πŸŽ₯ **Technical Recording Tips**
202
+
203
+ 1. **Use OBS Studio or similar** for high-quality screen recording
204
+ 2. **Record at 1080p** for clear text visibility
205
+ 3. **Use good microphone** for clear narration
206
+ 4. **Multiple takes OK** - edit together the best parts
207
+ 5. **Add captions** for accessibility
208
+ 6. **Include timestamps** in video description
209
+
210
+ ---
211
+
212
+ **Ready to showcase the future of agentic learning with MCP integration! πŸš€**
deployment_guide.md ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # πŸš€ Hugging Face Spaces Deployment Guide
2
+
3
+ ## πŸ“‹ Pre-Deployment Checklist
4
+
5
+ ### βœ… **Files Ready for Upload:**
6
+ - `space_app.py` - Main application file (Gradio + MCP server)
7
+ - `requirements.txt` - HF Spaces optimized dependencies
8
+ - `README_spaces.md` - Spaces configuration (rename to README.md)
9
+ - `config.py` - Configuration utilities
10
+ - `.env` - Environment variables (handle separately)
11
+
12
+ ### βœ… **Configuration Complete:**
13
+ - App file specified: `space_app.py`
14
+ - SDK: `gradio 4.44.0`
15
+ - Tags include: `mcp-server-track`
16
+ - License: MIT
17
+
18
+ ---
19
+
20
+ ## πŸ”§ **Deployment Steps**
21
+
22
+ ### **Step 1: Create Hugging Face Space**
23
+
24
+ 1. Go to [Hugging Face Spaces](https://huggingface.co/spaces)
25
+ 2. Click "Create new Space"
26
+ 3. **Important:** Create under the `Agents-MCP-Hackathon` organization
27
+ 4. Space name: `agentic-skill-builder`
28
+ 5. Choose "Gradio" as SDK
29
+ 6. Set to Public
30
+ 7. Click "Create Space"
31
+
32
+ ### **Step 2: Upload Files**
33
+
34
+ Upload these files to your new Space:
35
+
36
+ ```
37
+ πŸ“ agentic-skill-builder/
38
+ β”œβ”€β”€ πŸ“„ README.md (renamed from README_spaces.md)
39
+ β”œβ”€β”€ πŸ“„ space_app.py
40
+ β”œβ”€β”€ πŸ“„ requirements.txt
41
+ β”œβ”€β”€ πŸ“„ config.py
42
+ └── πŸ“„ .env (create in Spaces settings)
43
+ ```
44
+
45
+ ### **Step 3: Configure Environment Variables**
46
+
47
+ In your HF Space settings, add these environment variables:
48
+
49
+ ```env
50
+ AZURE_OPENAI_ENDPOINT=your-azure-endpoint
51
+ AZURE_OPENAI_KEY=your-api-key
52
+ AZURE_OPENAI_API_VERSION=2024-12-01-preview
53
+ AZURE_OPENAI_LLM_DEPLOYMENT=gpt-4.1
54
+ AZURE_OPENAI_LLM_MODEL=gpt-4.1
55
+ ```
56
+
57
+ **⚠️ Important:** Never commit your `.env` file with real credentials to a public repo!
58
+
59
+ ### **Step 4: Verify Deployment**
60
+
61
+ Once deployed, your Space should:
62
+ - βœ… Show the Gradio interface
63
+ - βœ… Respond to MCP endpoints at `https://your-space-name.hf.space/mcp/skills`
64
+ - βœ… Generate lessons and quizzes
65
+ - βœ… Include hackathon branding and MCP testing interface
66
+
67
+ ---
68
+
69
+ ## πŸ” **Testing Your Deployed Space**
70
+
71
+ ### **Gradio Interface Test:**
72
+ 1. Visit your Space URL
73
+ 2. Select a skill (e.g., "Python Programming")
74
+ 3. Complete the full learning flow
75
+ 4. Verify AI generates lessons and quizzes
76
+
77
+ ### **MCP Endpoints Test:**
78
+ ```bash
79
+ # Test from anywhere on the internet
80
+ curl https://your-space-name.hf.space/mcp/skills
81
+ curl https://your-space-name.hf.space/mcp/progress/test_user
82
+ ```
83
+
84
+ ---
85
+
86
+ ## πŸ“ **Post-Deployment Updates**
87
+
88
+ ### **Update README.md with:**
89
+ 1. **Live demo link:** Replace local URLs with your HF Space URL
90
+ 2. **Video link:** Add your demo video URL
91
+ 3. **Deployment status:** Confirm it's live and working
92
+
93
+ ### **Example Updates:**
94
+ ```markdown
95
+ ## 🎬 Demo Video
96
+ **MCP Server in Action:** [https://youtu.be/your-video-id](https://youtu.be/your-video-id)
97
+
98
+ ## 🌐 Live Demo
99
+ **Try it now:** [https://huggingface.co/spaces/Agents-MCP-Hackathon/agentic-skill-builder](https://huggingface.co/spaces/Agents-MCP-Hackathon/agentic-skill-builder)
100
+
101
+ ## πŸ”— MCP Endpoints
102
+ Test our live MCP server at: `https://your-space-name.hf.space/mcp/`
103
+ ```
104
+
105
+ ---
106
+
107
+ ## πŸ† **Final Hackathon Submission Checklist**
108
+
109
+ - [ ] βœ… Space deployed under Agents-MCP-Hackathon organization
110
+ - [ ] βœ… "mcp-server-track" tag in README
111
+ - [ ] βœ… Demo video uploaded and linked
112
+ - [ ] βœ… Live MCP endpoints working
113
+ - [ ] βœ… Gradio interface fully functional
114
+ - [ ] βœ… All dependencies working in cloud environment
115
+ - [ ] βœ… Documentation updated with live links
116
+
117
+ ---
118
+
119
+ ## 🚨 **Troubleshooting Common Issues**
120
+
121
+ ### **Build Failures:**
122
+ - Check `requirements.txt` for incompatible versions
123
+ - Verify all imports work in `space_app.py`
124
+ - Ensure environment variables are set correctly
125
+
126
+ ### **MCP Endpoints Not Working:**
127
+ - Verify FastAPI routes are properly configured
128
+ - Check if app.mount() is correctly set up
129
+ - Test endpoints locally first
130
+
131
+ ### **Azure OpenAI Errors:**
132
+ - Confirm environment variables are set in Spaces settings
133
+ - Check Azure OpenAI quota and model availability
134
+ - Verify API key permissions
135
+
136
+ ---
137
+
138
+ **Ready to deploy! Your agentic skill builder will be live for the world to see! 🌍✨**
hf-hackathon.code-workspace ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "folders": [
3
+ {
4
+ "path": "."
5
+ }
6
+ ],
7
+ "settings": {}
8
+ }
mcp_server.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MCP Server Integration for Agentic Skill Builder
3
+ This module provides Model Context Protocol endpoints for external agent integration.
4
+ """
5
+
6
+ import json
7
+ import asyncio
8
+ from typing import Dict, Any, List
9
+ from dataclasses import asdict
10
+ from datetime import datetime
11
+
12
+ from fastapi import FastAPI, HTTPException, Depends
13
+ from pydantic import BaseModel
14
+ import uvicorn
15
+
16
+ # Import from main app
17
+ from app import AgenticSkillBuilder, UserProgress
18
+
19
+ # FastAPI app for MCP endpoints
20
+ mcp_app = FastAPI(
21
+ title="Agentic Skill Builder MCP Server",
22
+ description="Model Context Protocol endpoints for microlearning integration",
23
+ version="1.0.0"
24
+ )
25
+
26
+ # Global app instance
27
+ skill_builder = AgenticSkillBuilder()
28
+
29
+ # Pydantic models for API
30
+ class LessonRequest(BaseModel):
31
+ skill: str
32
+ user_id: str = "default_user"
33
+ difficulty: str = "beginner"
34
+
35
+ class QuizSubmission(BaseModel):
36
+ user_id: str
37
+ skill: str
38
+ lesson_title: str
39
+ answers: List[str]
40
+
41
+ class ProgressResponse(BaseModel):
42
+ user_id: str
43
+ skill: str
44
+ lessons_completed: int
45
+ average_score: float
46
+ current_difficulty: str
47
+ recommendations: str
48
+
49
+ @mcp_app.get("/")
50
+ async def root():
51
+ """Root endpoint with API information"""
52
+ return {
53
+ "name": "Agentic Skill Builder MCP Server",
54
+ "version": "1.0.0",
55
+ "description": "MCP endpoints for AI-powered microlearning",
56
+ "endpoints": {
57
+ "GET /lesson/{skill}": "Fetch next lesson for a skill",
58
+ "GET /progress/{user_id}": "Get user progress data",
59
+ "POST /quiz/submit": "Submit quiz results",
60
+ "GET /skills": "List available skills"
61
+ }
62
+ }
63
+
64
+ @mcp_app.get("/skills")
65
+ async def get_available_skills():
66
+ """Get list of available predefined skills"""
67
+ return {
68
+ "predefined_skills": skill_builder.predefined_skills,
69
+ "custom_skills_supported": True,
70
+ "message": "You can also request lessons for any custom skill"
71
+ }
72
+
73
+ @mcp_app.post("/lesson/generate")
74
+ async def generate_lesson(request: LessonRequest):
75
+ """Generate a new lesson for the specified skill and user"""
76
+ try:
77
+ # Set current user
78
+ skill_builder.current_user = request.user_id
79
+
80
+ # Get user progress
81
+ progress = skill_builder.progress_agent.get_user_progress(
82
+ request.user_id, request.skill
83
+ )
84
+
85
+ # Generate lesson
86
+ lesson = await skill_builder.lesson_agent.generate_lesson(
87
+ skill=request.skill,
88
+ difficulty=request.difficulty or progress.current_difficulty,
89
+ previous_lessons=[] # Could be enhanced to track previous lessons
90
+ )
91
+
92
+ return {
93
+ "lesson": {
94
+ "title": lesson.title,
95
+ "content": lesson.content,
96
+ "skill": lesson.skill,
97
+ "difficulty": lesson.difficulty,
98
+ "duration_minutes": lesson.duration_minutes,
99
+ "key_concepts": lesson.key_concepts
100
+ },
101
+ "user_context": {
102
+ "user_id": request.user_id,
103
+ "current_difficulty": progress.current_difficulty,
104
+ "lessons_completed": progress.lessons_completed
105
+ },
106
+ "timestamp": datetime.now().isoformat()
107
+ }
108
+
109
+ except Exception as e:
110
+ raise HTTPException(status_code=500, detail=f"Error generating lesson: {str(e)}")
111
+
112
+ @mcp_app.get("/progress/{user_id}")
113
+ async def get_user_progress(user_id: str, skill: str = None):
114
+ """Get user progress data for all skills or a specific skill"""
115
+ try:
116
+ if skill:
117
+ # Get progress for specific skill
118
+ progress = skill_builder.progress_agent.get_user_progress(user_id, skill)
119
+ recommendation = skill_builder.progress_agent.get_recommendation(progress)
120
+
121
+ return ProgressResponse(
122
+ user_id=progress.user_id,
123
+ skill=progress.skill,
124
+ lessons_completed=progress.lessons_completed,
125
+ average_score=progress.get_average_score(),
126
+ current_difficulty=progress.current_difficulty,
127
+ recommendations=recommendation
128
+ )
129
+ else:
130
+ # Get progress for all skills
131
+ user_progress_data = {}
132
+ for key, progress in skill_builder.progress_agent.user_data.items():
133
+ if progress.user_id == user_id:
134
+ user_progress_data[progress.skill] = {
135
+ "lessons_completed": progress.lessons_completed,
136
+ "average_score": progress.get_average_score(),
137
+ "current_difficulty": progress.current_difficulty,
138
+ "quiz_scores": progress.quiz_scores,
139
+ "last_activity": progress.last_activity
140
+ }
141
+
142
+ return {
143
+ "user_id": user_id,
144
+ "skills_progress": user_progress_data,
145
+ "total_skills_learning": len(user_progress_data),
146
+ "timestamp": datetime.now().isoformat()
147
+ }
148
+
149
+ except Exception as e:
150
+ raise HTTPException(status_code=500, detail=f"Error fetching progress: {str(e)}")
151
+
152
+ @mcp_app.post("/quiz/submit")
153
+ async def submit_quiz_results(submission: QuizSubmission):
154
+ """Submit quiz results and get feedback"""
155
+ try:
156
+ # Set current user
157
+ skill_builder.current_user = submission.user_id
158
+
159
+ # Calculate score (simplified scoring)
160
+ if not skill_builder.current_quiz or len(submission.answers) == 0:
161
+ raise HTTPException(status_code=400, detail="No active quiz or no answers provided")
162
+
163
+ correct_answers = 0
164
+ total_questions = len(skill_builder.current_quiz.questions)
165
+
166
+ for i, (question, answer) in enumerate(zip(skill_builder.current_quiz.questions, submission.answers)):
167
+ if i >= len(submission.answers):
168
+ break
169
+
170
+ correct_answer = str(question['correct_answer']).lower()
171
+ user_answer = answer.lower().strip()
172
+
173
+ if user_answer == correct_answer:
174
+ correct_answers += 1
175
+
176
+ score = correct_answers / total_questions if total_questions > 0 else 0
177
+
178
+ # Update progress
179
+ progress = skill_builder.progress_agent.update_progress(
180
+ submission.user_id, submission.skill, quiz_score=score
181
+ )
182
+
183
+ # Get recommendation
184
+ recommendation = skill_builder.progress_agent.get_recommendation(progress)
185
+
186
+ return {
187
+ "quiz_results": {
188
+ "score": score,
189
+ "correct_answers": correct_answers,
190
+ "total_questions": total_questions,
191
+ "percentage": f"{score:.1%}"
192
+ },
193
+ "updated_progress": {
194
+ "lessons_completed": progress.lessons_completed,
195
+ "average_score": progress.get_average_score(),
196
+ "current_difficulty": progress.current_difficulty
197
+ },
198
+ "recommendation": recommendation,
199
+ "timestamp": datetime.now().isoformat()
200
+ }
201
+
202
+ except Exception as e:
203
+ raise HTTPException(status_code=500, detail=f"Error processing quiz submission: {str(e)}")
204
+
205
+ @mcp_app.post("/quiz/generate")
206
+ async def generate_quiz_for_lesson(lesson_title: str, skill: str, user_id: str = "default_user"):
207
+ """Generate a quiz for a specific lesson"""
208
+ try:
209
+ # Set current user
210
+ skill_builder.current_user = user_id
211
+
212
+ # Get user progress
213
+ progress = skill_builder.progress_agent.get_user_progress(user_id, skill)
214
+
215
+ # Create a mock lesson object for quiz generation
216
+ from app import Lesson
217
+ mock_lesson = Lesson(
218
+ title=lesson_title,
219
+ content=f"This is content for {lesson_title}",
220
+ skill=skill,
221
+ difficulty=progress.current_difficulty,
222
+ duration_minutes=5,
223
+ key_concepts=["concept1", "concept2"]
224
+ )
225
+
226
+ # Generate quiz
227
+ quiz = await skill_builder.quiz_agent.generate_quiz(mock_lesson, progress)
228
+
229
+ # Store current quiz for submission
230
+ skill_builder.current_quiz = quiz
231
+
232
+ return {
233
+ "quiz": {
234
+ "lesson_title": lesson_title,
235
+ "skill": skill,
236
+ "difficulty": quiz.difficulty,
237
+ "questions": quiz.questions
238
+ },
239
+ "instructions": "Submit answers using the /quiz/submit endpoint",
240
+ "timestamp": datetime.now().isoformat()
241
+ }
242
+
243
+ except Exception as e:
244
+ raise HTTPException(status_code=500, detail=f"Error generating quiz: {str(e)}")
245
+
246
+ @mcp_app.get("/health")
247
+ async def health_check():
248
+ """Health check endpoint"""
249
+ return {
250
+ "status": "healthy",
251
+ "timestamp": datetime.now().isoformat(),
252
+ "service": "Agentic Skill Builder MCP Server"
253
+ }
254
+
255
+ def run_mcp_server():
256
+ """Run the MCP server"""
257
+ uvicorn.run(
258
+ "mcp_server:mcp_app",
259
+ host="0.0.0.0",
260
+ port=8000,
261
+ reload=True,
262
+ log_level="info"
263
+ )
264
+
265
+ if __name__ == "__main__":
266
+ print("πŸš€ Starting Agentic Skill Builder MCP Server...")
267
+ print("πŸ“š MCP endpoints will be available at http://localhost:8000")
268
+ print("πŸ“– API documentation at http://localhost:8000/docs")
269
+ run_mcp_server()
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ gradio>=4.44.0
2
+ openai>=1.12.0
3
+ python-dotenv>=1.0.0
4
+ pandas>=2.0.0
5
+ uvicorn>=0.24.0
6
+ fastapi>=0.104.0
7
+ pydantic>=2.0.0
8
+ aiohttp>=3.9.0
9
+ requests>=2.31.0
run.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Launcher script for Agentic Skill Builder
3
+ Runs both the Gradio interface and MCP server
4
+ """
5
+
6
+ import asyncio
7
+ import subprocess
8
+ import sys
9
+ import time
10
+ import threading
11
+ from pathlib import Path
12
+
13
+ def run_gradio_app():
14
+ """Run the main Gradio application"""
15
+ print("πŸš€ Starting Gradio App...")
16
+ subprocess.run([sys.executable, "app.py"])
17
+
18
+ def run_mcp_server():
19
+ """Run the MCP server"""
20
+ print("πŸ”— Starting MCP Server...")
21
+ subprocess.run([sys.executable, "mcp_server.py"])
22
+
23
+ def main():
24
+ """Main launcher function"""
25
+ print("=" * 60)
26
+ print("πŸŽ“ AGENTIC SKILL BUILDER")
27
+ print(" AI-Powered Microlearning Platform")
28
+ print("=" * 60)
29
+ print()
30
+
31
+ # Check if we're in the right directory
32
+ if not Path("app.py").exists():
33
+ print("❌ Error: app.py not found. Please run this script from the project directory.")
34
+ return
35
+
36
+ print("Choose how to run the application:")
37
+ print("1. Gradio App only (recommended for demo)")
38
+ print("2. MCP Server only")
39
+ print("3. Both Gradio App and MCP Server")
40
+ print()
41
+
42
+ choice = input("Enter your choice (1-3): ").strip()
43
+
44
+ if choice == "1":
45
+ print("\n🎯 Starting Gradio App...")
46
+ print("πŸ“± Interface will be available at: http://localhost:7860")
47
+ run_gradio_app()
48
+
49
+ elif choice == "2":
50
+ print("\nπŸ”— Starting MCP Server...")
51
+ print("🌐 API will be available at: http://localhost:8000")
52
+ print("πŸ“š API docs at: http://localhost:8000/docs")
53
+ run_mcp_server()
54
+
55
+ elif choice == "3":
56
+ print("\nπŸš€ Starting both services...")
57
+ print("πŸ“± Gradio App: http://localhost:7860")
58
+ print("🌐 MCP Server: http://localhost:8000")
59
+ print("πŸ“š API docs: http://localhost:8000/docs")
60
+ print()
61
+
62
+ # Start MCP server in a separate thread
63
+ mcp_thread = threading.Thread(target=run_mcp_server, daemon=True)
64
+ mcp_thread.start()
65
+
66
+ # Give MCP server time to start
67
+ time.sleep(2)
68
+
69
+ # Start Gradio app (this will block)
70
+ run_gradio_app()
71
+
72
+ else:
73
+ print("❌ Invalid choice. Please run the script again.")
74
+
75
+ if __name__ == "__main__":
76
+ try:
77
+ main()
78
+ except KeyboardInterrupt:
79
+ print("\n\nπŸ‘‹ Goodbye! Thanks for using Agentic Skill Builder!")
80
+ except Exception as e:
81
+ print(f"\n❌ Error: {e}")
82
+ print("Please check your configuration and try again.")
space_app.py ADDED
@@ -0,0 +1,541 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Agentic Skill Builder - Hackathon Submission
3
+ A unified app.py that serves both Gradio interface and MCP server endpoints
4
+ for the Gradio Agents & MCP Hackathon 2025
5
+ """
6
+
7
+ import os
8
+ import json
9
+ import asyncio
10
+ import threading
11
+ import time
12
+ from datetime import datetime
13
+ from typing import Dict, List, Optional, Tuple
14
+ from dataclasses import dataclass, asdict
15
+ import logging
16
+
17
+ from dotenv import load_dotenv
18
+ import gradio as gr
19
+ from openai import AzureOpenAI
20
+ import pandas as pd
21
+ from fastapi import FastAPI, HTTPException
22
+ from pydantic import BaseModel
23
+ import uvicorn
24
+
25
+ # Configure logging
26
+ logging.basicConfig(level=logging.INFO)
27
+ logger = logging.getLogger(__name__)
28
+
29
+ # Load environment variables
30
+ load_dotenv()
31
+
32
+ # Azure OpenAI client configuration
33
+ client = AzureOpenAI(
34
+ azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT", "").replace('"', ''),
35
+ api_key=os.getenv("AZURE_OPENAI_KEY", "").replace('"', ''),
36
+ api_version=os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview").replace('"', ''),
37
+ )
38
+
39
+ # Model configurations
40
+ LLM_DEPLOYMENT = os.getenv("AZURE_OPENAI_LLM_DEPLOYMENT", "gpt-4").replace('"', '')
41
+ LLM_MODEL = os.getenv("AZURE_OPENAI_LLM_MODEL", "gpt-4").replace('"', '')
42
+
43
+ # Import all classes from the main app
44
+ from app import (
45
+ UserProgress, Lesson, Quiz, LessonAgent, QuizAgent,
46
+ ProgressAgent, AgenticSkillBuilder
47
+ )
48
+
49
+ # Create global instances
50
+ app_instance = AgenticSkillBuilder()
51
+
52
+ # ===== MCP SERVER INTEGRATION =====
53
+
54
+ # FastAPI app for MCP endpoints
55
+ mcp_app = FastAPI(
56
+ title="Agentic Skill Builder MCP Server",
57
+ description="Model Context Protocol endpoints for microlearning integration - Hackathon 2025",
58
+ version="1.0.0"
59
+ )
60
+
61
+ # Pydantic models for API
62
+ class LessonRequest(BaseModel):
63
+ skill: str
64
+ user_id: str = "default_user"
65
+ difficulty: str = "beginner"
66
+
67
+ class QuizSubmission(BaseModel):
68
+ user_id: str
69
+ skill: str
70
+ lesson_title: str
71
+ answers: List[str]
72
+
73
+ @mcp_app.get("/")
74
+ async def root():
75
+ """Root endpoint with hackathon information"""
76
+ return {
77
+ "name": "Agentic Skill Builder MCP Server",
78
+ "version": "1.0.0",
79
+ "hackathon": "Gradio Agents & MCP Hackathon 2025",
80
+ "track": "mcp-server-track",
81
+ "description": "MCP endpoints for AI-powered microlearning",
82
+ "endpoints": {
83
+ "GET /mcp/lesson/generate": "Generate next lesson for a skill",
84
+ "GET /mcp/progress/{user_id}": "Get user progress data",
85
+ "POST /mcp/quiz/submit": "Submit quiz results",
86
+ "GET /mcp/skills": "List available skills"
87
+ }
88
+ }
89
+
90
+ @mcp_app.get("/mcp/skills")
91
+ async def get_available_skills():
92
+ """Get list of available predefined skills"""
93
+ return {
94
+ "predefined_skills": app_instance.predefined_skills,
95
+ "custom_skills_supported": True,
96
+ "message": "You can also request lessons for any custom skill"
97
+ }
98
+
99
+ @mcp_app.post("/mcp/lesson/generate")
100
+ async def generate_lesson_mcp(request: LessonRequest):
101
+ """Generate a new lesson via MCP endpoint"""
102
+ try:
103
+ app_instance.current_user = request.user_id
104
+ progress = app_instance.progress_agent.get_user_progress(request.user_id, request.skill)
105
+
106
+ lesson = await app_instance.lesson_agent.generate_lesson(
107
+ skill=request.skill,
108
+ difficulty=request.difficulty or progress.current_difficulty,
109
+ previous_lessons=[]
110
+ )
111
+
112
+ return {
113
+ "lesson": {
114
+ "title": lesson.title,
115
+ "content": lesson.content,
116
+ "skill": lesson.skill,
117
+ "difficulty": lesson.difficulty,
118
+ "duration_minutes": lesson.duration_minutes,
119
+ "key_concepts": lesson.key_concepts
120
+ },
121
+ "user_context": {
122
+ "user_id": request.user_id,
123
+ "current_difficulty": progress.current_difficulty,
124
+ "lessons_completed": progress.lessons_completed
125
+ },
126
+ "mcp_server": "Agentic Skill Builder",
127
+ "timestamp": datetime.now().isoformat()
128
+ }
129
+
130
+ except Exception as e:
131
+ raise HTTPException(status_code=500, detail=f"Error generating lesson: {str(e)}")
132
+
133
+ @mcp_app.get("/mcp/progress/{user_id}")
134
+ async def get_user_progress_mcp(user_id: str, skill: str = None):
135
+ """Get user progress data via MCP endpoint"""
136
+ try:
137
+ if skill:
138
+ progress = app_instance.progress_agent.get_user_progress(user_id, skill)
139
+ recommendation = app_instance.progress_agent.get_recommendation(progress)
140
+
141
+ return {
142
+ "user_id": progress.user_id,
143
+ "skill": progress.skill,
144
+ "lessons_completed": progress.lessons_completed,
145
+ "average_score": progress.get_average_score(),
146
+ "current_difficulty": progress.current_difficulty,
147
+ "recommendations": recommendation,
148
+ "mcp_server": "Agentic Skill Builder"
149
+ }
150
+ else:
151
+ user_progress_data = {}
152
+ for key, progress in app_instance.progress_agent.user_data.items():
153
+ if progress.user_id == user_id:
154
+ user_progress_data[progress.skill] = {
155
+ "lessons_completed": progress.lessons_completed,
156
+ "average_score": progress.get_average_score(),
157
+ "current_difficulty": progress.current_difficulty,
158
+ "quiz_scores": progress.quiz_scores,
159
+ "last_activity": progress.last_activity
160
+ }
161
+
162
+ return {
163
+ "user_id": user_id,
164
+ "skills_progress": user_progress_data,
165
+ "total_skills_learning": len(user_progress_data),
166
+ "mcp_server": "Agentic Skill Builder",
167
+ "timestamp": datetime.now().isoformat()
168
+ }
169
+
170
+ except Exception as e:
171
+ raise HTTPException(status_code=500, detail=f"Error fetching progress: {str(e)}")
172
+
173
+ @mcp_app.post("/mcp/quiz/submit")
174
+ async def submit_quiz_results_mcp(submission: QuizSubmission):
175
+ """Submit quiz results via MCP endpoint"""
176
+ try:
177
+ app_instance.current_user = submission.user_id
178
+
179
+ if not app_instance.current_quiz or len(submission.answers) == 0:
180
+ raise HTTPException(status_code=400, detail="No active quiz or no answers provided")
181
+
182
+ correct_answers = 0
183
+ total_questions = len(app_instance.current_quiz.questions)
184
+
185
+ for i, (question, answer) in enumerate(zip(app_instance.current_quiz.questions, submission.answers)):
186
+ if i >= len(submission.answers):
187
+ break
188
+
189
+ correct_answer = str(question['correct_answer']).lower()
190
+ user_answer = answer.lower().strip()
191
+
192
+ if user_answer == correct_answer:
193
+ correct_answers += 1
194
+
195
+ score = correct_answers / total_questions if total_questions > 0 else 0
196
+
197
+ progress = app_instance.progress_agent.update_progress(
198
+ submission.user_id, submission.skill, quiz_score=score
199
+ )
200
+
201
+ recommendation = app_instance.progress_agent.get_recommendation(progress)
202
+
203
+ return {
204
+ "quiz_results": {
205
+ "score": score,
206
+ "correct_answers": correct_answers,
207
+ "total_questions": total_questions,
208
+ "percentage": f"{score:.1%}"
209
+ },
210
+ "updated_progress": {
211
+ "lessons_completed": progress.lessons_completed,
212
+ "average_score": progress.get_average_score(),
213
+ "current_difficulty": progress.current_difficulty
214
+ },
215
+ "recommendation": recommendation,
216
+ "mcp_server": "Agentic Skill Builder",
217
+ "timestamp": datetime.now().isoformat()
218
+ }
219
+
220
+ except Exception as e:
221
+ raise HTTPException(status_code=500, detail=f"Error processing quiz submission: {str(e)}")
222
+
223
+ # ===== GRADIO INTERFACE =====
224
+
225
+ def create_interface():
226
+ """Create the Gradio interface with enhanced hackathon features"""
227
+
228
+ with gr.Blocks(
229
+ title="Agentic Skill Builder - MCP Hackathon 2025",
230
+ theme=gr.themes.Soft(),
231
+ css="""
232
+ .gradio-container {
233
+ max-width: 900px !important;
234
+ margin: auto !important;
235
+ }
236
+ .hackathon-header {
237
+ background: linear-gradient(90deg, #ff7b7b, #667eea);
238
+ color: white;
239
+ padding: 1rem;
240
+ border-radius: 10px;
241
+ margin-bottom: 1rem;
242
+ }
243
+ """
244
+ ) as demo:
245
+
246
+ # Enhanced Header for Hackathon
247
+ gr.HTML("""
248
+ <div class="hackathon-header">
249
+ <h1>πŸš€ Agentic Skill Builder</h1>
250
+ <h3>AI-Powered Microlearning with MCP Integration</h3>
251
+ <p><strong>πŸ† Gradio Agents & MCP Hackathon 2025 Submission</strong></p>
252
+ <p>Track: MCP Server/Tool β€’ Demonstrating Agentic AI Workflows</p>
253
+ </div>
254
+ """)
255
+
256
+ # State variables
257
+ current_skill = gr.State("")
258
+
259
+ with gr.Tab("🎯 Microlearning Experience"):
260
+ gr.Markdown("""
261
+ ### πŸŽ“ Start Your AI-Powered Learning Journey
262
+ Choose any skill and let our agentic AI system create personalized lessons and adaptive quizzes for you!
263
+ """)
264
+
265
+ with gr.Row():
266
+ with gr.Column():
267
+ skill_dropdown = gr.Dropdown(
268
+ choices=app_instance.predefined_skills,
269
+ label="πŸ“š Select a Popular Skill",
270
+ info="Choose from trending skills..."
271
+ )
272
+ custom_skill = gr.Textbox(
273
+ label="✍️ Or Enter Any Custom Skill",
274
+ info="e.g., Quantum Computing, Meditation, Game Development...",
275
+ placeholder="What would you like to learn today?"
276
+ )
277
+
278
+ start_btn = gr.Button("πŸš€ Start Learning", variant="primary", size="lg")
279
+
280
+ # Learning content areas
281
+ lesson_output = gr.Markdown(visible=False)
282
+ lesson_btn = gr.Button("Complete Lesson", visible=False)
283
+
284
+ quiz_output = gr.Markdown(visible=False)
285
+ quiz_inputs = []
286
+ for i in range(5):
287
+ quiz_inputs.append(gr.Textbox(label=f"Answer {i+1}", visible=False))
288
+
289
+ quiz_submit_btn = gr.Button("Submit Quiz", visible=False)
290
+ results_output = gr.Markdown(visible=False)
291
+ restart_btn = gr.Button("Start New Lesson", visible=False)
292
+
293
+ with gr.Tab("πŸ“Š Progress Analytics"):
294
+ gr.Markdown("### πŸ“ˆ Your Learning Analytics Dashboard")
295
+ progress_display = gr.Markdown("Complete some lessons to see your learning analytics!")
296
+ refresh_progress_btn = gr.Button("πŸ”„ Refresh Progress")
297
+
298
+ with gr.Tab("πŸ”— MCP Server Demo"):
299
+ gr.Markdown("""
300
+ ### πŸ€– Model Context Protocol Integration
301
+
302
+ **This app is BOTH a Gradio interface AND an MCP server!**
303
+
304
+ #### 🌐 Available MCP Endpoints:
305
+
306
+ - **GET `/mcp/skills`** - List available learning skills
307
+ - **POST `/mcp/lesson/generate`** - Generate personalized lessons
308
+ - **GET `/mcp/progress/{user_id}`** - Get learning progress data
309
+ - **POST `/mcp/quiz/submit`** - Submit quiz answers
310
+
311
+ #### πŸ§ͺ Try the MCP Server:
312
+
313
+ The MCP server is running alongside this Gradio interface! External agents can connect to these endpoints to:
314
+ - Generate lessons for any skill
315
+ - Track learning progress
316
+ - Submit quiz results
317
+ - Access learning analytics
318
+
319
+ **Example MCP Usage:**
320
+ ```bash
321
+ # Get available skills
322
+ curl https://your-space-url.com/mcp/skills
323
+
324
+ # Generate a lesson
325
+ curl -X POST https://your-space-url.com/mcp/lesson/generate \\
326
+ -H "Content-Type: application/json" \\
327
+ -d '{"skill": "Python Programming", "user_id": "agent_user"}'
328
+ ```
329
+
330
+ #### 🎯 Hackathon Innovation:
331
+ - **Agentic Architecture**: Multiple AI agents (Lesson, Quiz, Progress) collaborate
332
+ - **MCP Protocol**: Full Model Context Protocol implementation
333
+ - **Adaptive Learning**: AI adjusts difficulty based on performance
334
+ - **Real-time Integration**: Seamless connection between UI and MCP endpoints
335
+ """)
336
+
337
+ # MCP Demo Interface
338
+ gr.Markdown("#### πŸ§ͺ Test MCP Endpoints Directly:")
339
+
340
+ with gr.Row():
341
+ with gr.Column():
342
+ mcp_skill_input = gr.Textbox(label="Skill for MCP Test", value="Python Programming")
343
+ mcp_user_input = gr.Textbox(label="User ID for MCP Test", value="mcp_test_user")
344
+ mcp_test_btn = gr.Button("πŸ§ͺ Test MCP Lesson Generation", variant="secondary")
345
+
346
+ with gr.Column():
347
+ mcp_output = gr.JSON(label="MCP Server Response")
348
+
349
+ # Event handlers (same as original app.py)
350
+ async def handle_start_learning(skill_choice, custom_skill_input):
351
+ skill = custom_skill_input.strip() if custom_skill_input.strip() else skill_choice
352
+ if not skill:
353
+ return [
354
+ gr.update(value="⚠️ Please select or enter a skill to continue."),
355
+ gr.update(visible=False),
356
+ gr.update(visible=False),
357
+ skill
358
+ ] + [gr.update(visible=False, value="") for _ in range(5)]
359
+
360
+ lesson_content, btn_text, _ = await app_instance.start_lesson(skill)
361
+
362
+ return [
363
+ gr.update(value=lesson_content),
364
+ gr.update(value=btn_text, visible=True),
365
+ gr.update(visible=False),
366
+ skill
367
+ ] + [gr.update(visible=False, value="") for _ in range(5)]
368
+
369
+ async def handle_complete_lesson():
370
+ quiz_content, btn_text, _ = await app_instance.complete_lesson_and_start_quiz()
371
+
372
+ quiz_updates = []
373
+ if app_instance.current_quiz:
374
+ for i, question in enumerate(app_instance.current_quiz.questions):
375
+ if i < len(quiz_inputs):
376
+ label = f"Q{i+1}: {question['question'][:50]}..."
377
+ quiz_updates.append(gr.update(label=label, visible=True))
378
+ else:
379
+ quiz_updates.append(gr.update(visible=False))
380
+ for i in range(len(app_instance.current_quiz.questions), len(quiz_inputs)):
381
+ quiz_updates.append(gr.update(visible=False))
382
+ else:
383
+ quiz_updates = [gr.update(visible=False) for _ in range(len(quiz_inputs))]
384
+
385
+ return [
386
+ gr.update(visible=False),
387
+ gr.update(value=quiz_content, visible=True),
388
+ gr.update(value=btn_text, visible=True),
389
+ gr.update(visible=False)
390
+ ] + quiz_updates
391
+
392
+ def handle_submit_quiz(*answers):
393
+ valid_answers = [ans for ans in answers if ans is not None and ans != ""]
394
+ results_content, btn_text, _ = app_instance.submit_quiz(*valid_answers)
395
+
396
+ return [
397
+ gr.update(visible=False),
398
+ gr.update(value=results_content, visible=True),
399
+ gr.update(value=btn_text, visible=True),
400
+ gr.update(visible=False)
401
+ ] + [gr.update(visible=False) for _ in range(len(quiz_inputs))]
402
+
403
+ def handle_restart():
404
+ return [
405
+ gr.update(visible=False),
406
+ gr.update(visible=False),
407
+ gr.update(visible=False),
408
+ gr.update(visible=False),
409
+ gr.update(visible=False),
410
+ ""
411
+ ] + [gr.update(visible=False, value="") for _ in range(len(quiz_inputs))]
412
+
413
+ def update_progress_display():
414
+ if not app_instance.progress_agent.user_data:
415
+ return "**No learning data yet.** Complete some lessons to see your progress!"
416
+
417
+ progress_content = "# πŸ“Š Your Learning Progress\n\n"
418
+ for key, progress in app_instance.progress_agent.user_data.items():
419
+ progress_content += f"""
420
+ **Skill:** {progress.skill}
421
+ - Lessons completed: {progress.lessons_completed}
422
+ - Average quiz score: {progress.get_average_score():.1%}
423
+ - Current difficulty: {progress.current_difficulty.title()}
424
+ - Last activity: {progress.last_activity or 'Never'}
425
+
426
+ """
427
+ return progress_content
428
+
429
+ async def test_mcp_endpoint(skill, user_id):
430
+ """Test MCP endpoint directly from the interface"""
431
+ try:
432
+ # Simulate MCP endpoint call
433
+ request_data = {
434
+ "skill": skill,
435
+ "user_id": user_id,
436
+ "difficulty": "beginner"
437
+ }
438
+
439
+ # Generate lesson using the app instance
440
+ app_instance.current_user = user_id
441
+ progress = app_instance.progress_agent.get_user_progress(user_id, skill)
442
+ lesson = await app_instance.lesson_agent.generate_lesson(skill, progress.current_difficulty, [])
443
+
444
+ response = {
445
+ "mcp_endpoint": "/mcp/lesson/generate",
446
+ "request": request_data,
447
+ "response": {
448
+ "lesson": {
449
+ "title": lesson.title,
450
+ "content": lesson.content[:200] + "...", # Truncated for display
451
+ "skill": lesson.skill,
452
+ "difficulty": lesson.difficulty,
453
+ "duration_minutes": lesson.duration_minutes,
454
+ "key_concepts": lesson.key_concepts
455
+ },
456
+ "user_context": {
457
+ "user_id": user_id,
458
+ "current_difficulty": progress.current_difficulty,
459
+ "lessons_completed": progress.lessons_completed
460
+ },
461
+ "mcp_server": "Agentic Skill Builder",
462
+ "status": "success"
463
+ }
464
+ }
465
+
466
+ return response
467
+
468
+ except Exception as e:
469
+ return {
470
+ "mcp_endpoint": "/mcp/lesson/generate",
471
+ "error": str(e),
472
+ "status": "error"
473
+ }
474
+
475
+ # Wire up events
476
+ start_btn.click(
477
+ handle_start_learning,
478
+ inputs=[skill_dropdown, custom_skill],
479
+ outputs=[lesson_output, lesson_btn, quiz_output, current_skill] + quiz_inputs[:5]
480
+ )
481
+
482
+ lesson_btn.click(
483
+ handle_complete_lesson,
484
+ outputs=[lesson_btn, quiz_output, quiz_submit_btn, results_output] + quiz_inputs
485
+ )
486
+
487
+ quiz_submit_btn.click(
488
+ handle_submit_quiz,
489
+ inputs=quiz_inputs,
490
+ outputs=[quiz_submit_btn, results_output, restart_btn, quiz_output] + quiz_inputs
491
+ )
492
+
493
+ restart_btn.click(
494
+ handle_restart,
495
+ outputs=[lesson_output, quiz_output, results_output, lesson_btn, restart_btn, current_skill] + quiz_inputs
496
+ )
497
+
498
+ refresh_progress_btn.click(
499
+ update_progress_display,
500
+ outputs=[progress_display]
501
+ )
502
+
503
+ mcp_test_btn.click(
504
+ test_mcp_endpoint,
505
+ inputs=[mcp_skill_input, mcp_user_input],
506
+ outputs=[mcp_output]
507
+ )
508
+
509
+ return demo
510
+
511
+ # ===== MAIN APPLICATION =====
512
+
513
+ def run_mcp_server():
514
+ """Run the MCP server in a separate thread"""
515
+ uvicorn.run(
516
+ mcp_app,
517
+ host="0.0.0.0",
518
+ port=8001, # Different port to avoid conflicts
519
+ log_level="info"
520
+ )
521
+
522
+ def main():
523
+ """Main application entry point for Hugging Face Spaces"""
524
+ # Start MCP server in background thread
525
+ mcp_thread = threading.Thread(target=run_mcp_server, daemon=True)
526
+ mcp_thread.start()
527
+
528
+ # Give MCP server time to start
529
+ time.sleep(2)
530
+
531
+ # Create and launch Gradio interface
532
+ demo = create_interface()
533
+ demo.launch(
534
+ server_name="0.0.0.0",
535
+ server_port=7860,
536
+ share=True, # Enable sharing for demo purposes
537
+ show_error=True
538
+ )
539
+
540
+ if __name__ == "__main__":
541
+ main()
validate_hackathon.py ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Hackathon Validation Script
3
+ Tests the MCP server functionality for submission requirements
4
+ """
5
+
6
+ import asyncio
7
+ import requests
8
+ import time
9
+ import subprocess
10
+ import threading
11
+ from datetime import datetime
12
+
13
+ def test_mcp_server_endpoints():
14
+ """Test MCP server endpoints to ensure hackathon compliance"""
15
+ print("πŸ§ͺ HACKATHON VALIDATION - MCP SERVER TESTING")
16
+ print("=" * 60)
17
+
18
+ base_url = "http://localhost:8001" # MCP server port
19
+
20
+ tests = [
21
+ ("Root endpoint", "GET", "/"),
22
+ ("Skills list", "GET", "/mcp/skills"),
23
+ ("Progress endpoint", "GET", "/mcp/progress/test_user"),
24
+ ]
25
+
26
+ print(f"🌐 Testing MCP server at {base_url}")
27
+ print(f"πŸ“‹ Running {len(tests)} endpoint tests...\n")
28
+
29
+ results = []
30
+
31
+ for test_name, method, endpoint in tests:
32
+ try:
33
+ url = f"{base_url}{endpoint}"
34
+ print(f"πŸ”„ Testing {test_name}: {method} {endpoint}")
35
+
36
+ if method == "GET":
37
+ response = requests.get(url, timeout=5)
38
+ elif method == "POST":
39
+ response = requests.post(url, json={}, timeout=5)
40
+
41
+ if response.status_code == 200:
42
+ print(f" βœ… SUCCESS: {response.status_code}")
43
+ try:
44
+ data = response.json()
45
+ if "mcp" in str(data).lower() or "agentic" in str(data).lower():
46
+ print(f" 🎯 MCP-compliant response detected")
47
+ except:
48
+ pass
49
+ results.append((test_name, True, response.status_code))
50
+ else:
51
+ print(f" ❌ FAILED: {response.status_code}")
52
+ results.append((test_name, False, response.status_code))
53
+
54
+ except requests.exceptions.RequestException as e:
55
+ print(f" ❌ CONNECTION ERROR: {e}")
56
+ results.append((test_name, False, "Connection Error"))
57
+
58
+ print()
59
+
60
+ # Summary
61
+ print("πŸ“Š TEST SUMMARY")
62
+ print("-" * 40)
63
+ passed = sum(1 for _, success, _ in results if success)
64
+ total = len(results)
65
+ print(f"βœ… Passed: {passed}/{total}")
66
+
67
+ if passed == total:
68
+ print("πŸŽ‰ ALL MCP ENDPOINT TESTS PASSED!")
69
+ else:
70
+ print("⚠️ Some tests failed. Check the MCP server.")
71
+
72
+ return results
73
+
74
+ def test_post_endpoints():
75
+ """Test POST endpoints with sample data"""
76
+ print("\nπŸ§ͺ TESTING POST ENDPOINTS")
77
+ print("=" * 40)
78
+
79
+ base_url = "http://localhost:8001"
80
+
81
+ # Test lesson generation
82
+ try:
83
+ print("πŸ”„ Testing lesson generation...")
84
+ lesson_data = {
85
+ "skill": "Python Programming",
86
+ "user_id": "test_user",
87
+ "difficulty": "beginner"
88
+ }
89
+ response = requests.post(f"{base_url}/mcp/lesson/generate", json=lesson_data, timeout=10)
90
+ if response.status_code == 200:
91
+ print(" βœ… Lesson generation successful")
92
+ data = response.json()
93
+ if "lesson" in data:
94
+ print(" 🎯 Lesson data structure valid")
95
+ else:
96
+ print(f" ❌ Lesson generation failed: {response.status_code}")
97
+ except Exception as e:
98
+ print(f" ❌ Lesson generation error: {e}")
99
+
100
+ # Test quiz submission
101
+ try:
102
+ print("πŸ”„ Testing quiz submission...")
103
+ quiz_data = {
104
+ "user_id": "test_user",
105
+ "skill": "Python Programming",
106
+ "lesson_title": "Variables and Data Types",
107
+ "answers": ["correct", "incorrect", "correct"]
108
+ }
109
+ response = requests.post(f"{base_url}/mcp/quiz/submit", json=quiz_data, timeout=10)
110
+ if response.status_code == 200:
111
+ print(" βœ… Quiz submission successful")
112
+ else:
113
+ print(f" ❌ Quiz submission failed: {response.status_code}")
114
+ except Exception as e:
115
+ print(f" ❌ Quiz submission error: {e}")
116
+
117
+ def validate_hackathon_requirements():
118
+ """Validate all hackathon submission requirements"""
119
+ print("\nπŸ† HACKATHON SUBMISSION VALIDATION")
120
+ print("=" * 50)
121
+
122
+ requirements = []
123
+
124
+ # Check README.md for required tag
125
+ try:
126
+ with open("README.md", "r", encoding="utf-8") as f:
127
+ readme_content = f.read()
128
+ if "mcp-server-track" in readme_content:
129
+ print("βœ… README.md contains 'mcp-server-track' tag")
130
+ requirements.append(("README tag", True))
131
+ else:
132
+ print("❌ README.md missing 'mcp-server-track' tag")
133
+ requirements.append(("README tag", False))
134
+ except FileNotFoundError:
135
+ print("❌ README.md not found")
136
+ requirements.append(("README file", False))
137
+
138
+ # Check for demo video link
139
+ try:
140
+ with open("README.md", "r", encoding="utf-8") as f:
141
+ readme_content = f.read()
142
+ if "demo-video-link.com" in readme_content or "your-demo-video-link.com" in readme_content:
143
+ print("⚠️ Demo video link is placeholder - needs actual video")
144
+ requirements.append(("Demo video", False))
145
+ elif any(video_keyword in readme_content.lower() for video_keyword in ["youtube.com", "vimeo.com", "loom.com", "demo video"]):
146
+ print("βœ… Demo video link appears to be present")
147
+ requirements.append(("Demo video", True))
148
+ else:
149
+ print("❌ Demo video link not found")
150
+ requirements.append(("Demo video", False))
151
+ except:
152
+ requirements.append(("Demo video check", False))
153
+
154
+ # Check space_app.py exists and has MCP endpoints
155
+ try:
156
+ with open("space_app.py", "r", encoding="utf-8") as f:
157
+ app_content = f.read()
158
+ if "FastAPI" in app_content and "@mcp_app" in app_content:
159
+ print("βœ… space_app.py has MCP server integration")
160
+ requirements.append(("MCP integration", True))
161
+ else:
162
+ print("❌ space_app.py missing MCP server integration")
163
+ requirements.append(("MCP integration", False))
164
+ except FileNotFoundError:
165
+ print("❌ space_app.py not found")
166
+ requirements.append(("Main app file", False))
167
+
168
+ # Check requirements.txt
169
+ try:
170
+ with open("requirements.txt", "r") as f:
171
+ reqs = f.read()
172
+ if "gradio" in reqs and "fastapi" in reqs:
173
+ print("βœ… requirements.txt has necessary dependencies")
174
+ requirements.append(("Dependencies", True))
175
+ else:
176
+ print("❌ requirements.txt missing key dependencies")
177
+ requirements.append(("Dependencies", False))
178
+ except FileNotFoundError:
179
+ print("❌ requirements.txt not found")
180
+ requirements.append(("Requirements file", False))
181
+
182
+ print("\nπŸ“‹ SUBMISSION CHECKLIST")
183
+ print("-" * 30)
184
+ passed = sum(1 for _, success in requirements if success)
185
+ total = len(requirements)
186
+
187
+ for req_name, success in requirements:
188
+ status = "βœ…" if success else "❌"
189
+ print(f"{status} {req_name}")
190
+
191
+ print(f"\nπŸ“Š Overall Score: {passed}/{total}")
192
+
193
+ if passed == total:
194
+ print("πŸŽ‰ READY FOR HACKATHON SUBMISSION!")
195
+ else:
196
+ print("⚠️ Please address the failed requirements above.")
197
+
198
+ return requirements
199
+
200
+ def main():
201
+ """Main validation function"""
202
+ print("πŸš€ AGENTIC SKILL BUILDER - HACKATHON VALIDATION")
203
+ print("=" * 60)
204
+ print(f"⏰ Validation Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
205
+ print()
206
+
207
+ # First validate file-based requirements
208
+ validate_hackathon_requirements()
209
+
210
+ # Ask user if they want to test the running server
211
+ print("\n" + "="*60)
212
+ print("🌐 MCP SERVER TESTING")
213
+ print("To test MCP endpoints, the server should be running on localhost:8001")
214
+ print("You can start it with: python space_app.py")
215
+
216
+ try:
217
+ # Try to test if server is running
218
+ response = requests.get("http://localhost:8001", timeout=2)
219
+ print("βœ… Server detected running!")
220
+ test_mcp_server_endpoints()
221
+ test_post_endpoints()
222
+ except:
223
+ print("⚠️ Server not detected. Start the server to test MCP endpoints.")
224
+ print(" Command: python space_app.py")
225
+
226
+ print("\n" + "="*60)
227
+ print("🎯 NEXT STEPS FOR HACKATHON SUBMISSION:")
228
+ print("1. πŸ“Ή Record demo video showing MCP server in action")
229
+ print("2. πŸ”— Update README.md with actual demo video link")
230
+ print("3. πŸš€ Upload to Hugging Face Spaces under Agents-MCP-Hackathon org")
231
+ print("4. βœ… Ensure all MCP endpoints work in the deployed Space")
232
+ print("=" * 60)
233
+
234
+ if __name__ == "__main__":
235
+ main()