Files changed (12) hide show
  1. .env.local +1 -0
  2. .gitignore +21 -13
  3. App.tsx +59 -0
  4. README.md +13 -79
  5. index.css +20 -0
  6. index.html +53 -0
  7. index.tsx +20 -0
  8. metadata.json +6 -0
  9. package.json +24 -0
  10. tsconfig.json +29 -0
  11. types.ts +200 -0
  12. vite.config.ts +17 -0
.env.local ADDED
@@ -0,0 +1 @@
 
 
1
+ GEMINI_API_KEY=PLACEHOLDER_API_KEY
.gitignore CHANGED
@@ -1,16 +1,24 @@
1
- # Python-generated files
2
- __pycache__/
3
- *.py[oc]
4
- build/
5
- dist/
6
- wheels/
7
- *.egg-info
 
8
 
9
- # Virtual environments
10
- .venv
11
-
12
- .env
13
 
 
 
 
14
  .idea
15
-
16
- .python-version
 
 
 
 
 
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
 
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
 
15
+ # Editor directories and files
16
+ .vscode/*
17
+ !.vscode/extensions.json
18
  .idea
19
+ .DS_Store
20
+ *.suo
21
+ *.ntvs*
22
+ *.njsproj
23
+ *.sln
24
+ *.sw?
App.tsx ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import React, { useState } from 'react';
7
+ import LoginScreen from './components/LoginScreen';
8
+ import AppLayout from './components/AppLayout';
9
+ import DoctorRegistration from './components/DoctorRegistration';
10
+ import { users as mockUsers } from './data/mockData';
11
+ import type { User } from './types';
12
+
13
+ // In a real app, this would be managed in a global state (Context, Redux, etc.)
14
+ let users = [...mockUsers];
15
+
16
+ const App: React.FC = () => {
17
+ const [currentUser, setCurrentUser] = useState<User | null>(null);
18
+ const [isCompletingDoctorProfile, setIsCompletingDoctorProfile] = useState(false);
19
+
20
+ const handleLoginSuccess = (user: User) => {
21
+ setCurrentUser(user);
22
+ if (user.role === 'doctor') {
23
+ // This is a simplification. In a real app, you'd check if their profile is complete.
24
+ // For the demo, we assume if they log in, their profile is complete.
25
+ setIsCompletingDoctorProfile(false);
26
+ }
27
+ };
28
+
29
+ const handleLogout = () => {
30
+ setCurrentUser(null);
31
+ setIsCompletingDoctorProfile(false);
32
+ };
33
+
34
+ const handleRegisterSuccess = (newUser: User) => {
35
+ // In a real app, you would add the user to the database.
36
+ // Here, we'll just log them in directly.
37
+ users.push(newUser); // Simulate adding to DB
38
+ setCurrentUser(newUser);
39
+ if (newUser.role === 'doctor') {
40
+ setIsCompletingDoctorProfile(true);
41
+ }
42
+ };
43
+
44
+ const handleDoctorRegistrationComplete = () => {
45
+ setIsCompletingDoctorProfile(false);
46
+ };
47
+
48
+ if (currentUser && currentUser.role === 'doctor' && isCompletingDoctorProfile) {
49
+ return <DoctorRegistration user={currentUser} onRegistrationComplete={handleDoctorRegistrationComplete} />;
50
+ }
51
+
52
+ if (!currentUser) {
53
+ return <LoginScreen onLoginSuccess={handleLoginSuccess} onRegisterSuccess={handleRegisterSuccess} />;
54
+ }
55
+
56
+ return <AppLayout currentUser={currentUser} onLogout={handleLogout} />;
57
+ };
58
+
59
+ export default App;
README.md CHANGED
@@ -1,86 +1,20 @@
1
- ---
2
- title: Rag Mcp Server
3
- emoji: 🏢
4
- colorFrom: indigo
5
- colorTo: pink
6
- sdk: gradio
7
- sdk_version: 5.31.0
8
- app_file: app.py
9
- pinned: false
10
- short_description: 'This space defines a RAG MCP server '
11
- ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
14
 
15
- # Rag MCP server
16
 
17
- This is a simple gradio server that allows you to run a RAG (Retrieval-Augmented Generation) model using the
18
- MCP (Model Control Protocol) interface.
19
 
20
- # Requirements
21
 
22
- - UV: The python package manager. Visit https://github.com/astral-sh/uv
23
 
24
- Since the server uses SERPER API, you will need to set the `SERPER_API_KEY` environment variable to
25
- enable the search functionality. You can export it in your shell:
26
 
27
- ```bash
28
- export SERPER_API_KEY=your_serper_api_key
29
- ```
30
-
31
- # Installation
32
-
33
- ```bash
34
- uv sync
35
- ```
36
-
37
- # Usage
38
-
39
- Just run the gradio application:
40
-
41
- ```bash
42
- uv run gradio app.py
43
- ```
44
-
45
- # Access the server
46
-
47
- Open your browser and go to `http://localhost:7860` to access the RAG MCP server.
48
-
49
- You can see the [gradio docs](https://www.gradio.app/guides/building-mcp-server-with-gradio) for more information on how
50
- to use the interface.
51
-
52
- # Using the MCP server with a mpc client
53
-
54
- You can use the tiny-agents client to interact with the MCP server. To do this, you need to install the huggingface_hub
55
- package:
56
-
57
- ```bash
58
- pip install huggingface_hub
59
- ```
60
-
61
- Then, you can use the following code to interact with the MCP server:
62
-
63
- ```bash
64
- export HF_TOKEN=your_huggingface_token
65
-
66
- tiny_agents run agent.json
67
- ```
68
-
69
- The `agent.json` file contains the configuration for the MCP client. Here is an example of how to create this file:
70
-
71
- ```json
72
- {
73
- "model": "meta-llama/Llama-3.3-70B-Instruct",
74
- "provider": "cerebras",
75
- "servers": [
76
- {
77
- "type": "sse",
78
- "config": {
79
- "url": "https://frascuchon-rag-mcp-server.hf.space/gradio_api/mcp/sse"
80
- }
81
- }
82
- ]
83
- }
84
- ```
85
-
86
- You can change the server URL to point to your own MCP server if you are running it locally or on a different host.
 
1
+ <div align="center">
2
+ <img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
3
+ </div>
 
 
 
 
 
 
 
 
4
 
5
+ # Run and deploy your AI Studio app
6
 
7
+ This contains everything you need to run your app locally.
8
 
9
+ View your app in AI Studio: https://ai.studio/apps/drive/19IkjTQRuXNjcLCE75qSjPELo7PorJbli
 
10
 
11
+ ## Run Locally
12
 
13
+ **Prerequisites:** Node.js
14
 
 
 
15
 
16
+ 1. Install dependencies:
17
+ `npm install`
18
+ 2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
19
+ 3. Run the app:
20
+ `npm run dev`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
index.css ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer utilities {
6
+ .animate-fade-in {
7
+ animation: fadeIn 0.5s ease-in-out;
8
+ }
9
+
10
+ @keyframes fadeIn {
11
+ from {
12
+ opacity: 0;
13
+ transform: translateY(10px);
14
+ }
15
+ to {
16
+ opacity: 1;
17
+ transform: translateY(0);
18
+ }
19
+ }
20
+ }
index.html ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Mostasheer</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script type="importmap">
10
+ {
11
+ "imports": {
12
+ "react": "https://esm.sh/react@19.0.0-rc-6230622a1a-20240610",
13
+ "react-dom/client": "https://esm.sh/react-dom@19.0.0-rc-6230622a1a-20240610/client",
14
+ "@google/genai": "https://esm.sh/@google/genai@^0.14.0",
15
+ "react/": "https://aistudiocdn.com/react@^19.1.1/",
16
+ "react-dom/": "https://aistudiocdn.com/react-dom@^19.1.1/",
17
+ "typeorm": "https://aistudiocdn.com/typeorm@^0.3.26",
18
+ "@nestjs/common": "https://aistudiocdn.com/@nestjs/common@^11.1.6",
19
+ "@nestjs/typeorm": "https://aistudiocdn.com/@nestjs/typeorm@^11.0.0"
20
+ }
21
+ }
22
+ </script>
23
+ <link rel="preconnect" href="https://fonts.googleapis.com">
24
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
25
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
26
+ <style>
27
+ body {
28
+ font-family: 'Inter', sans-serif;
29
+ background-color: #f4f7f6;
30
+ color: #1a202c;
31
+ }
32
+ /* For custom scrollbars */
33
+ ::-webkit-scrollbar {
34
+ width: 8px;
35
+ }
36
+ ::-webkit-scrollbar-track {
37
+ background: #e0e0e0;
38
+ }
39
+ ::-webkit-scrollbar-thumb {
40
+ background: #a0a0a0;
41
+ border-radius: 4px;
42
+ }
43
+ ::-webkit-scrollbar-thumb:hover {
44
+ background: #808080;
45
+ }
46
+ </style>
47
+ <link rel="stylesheet" href="/index.css">
48
+ </head>
49
+ <body>
50
+ <div id="root"></div>
51
+ <script type="module" src="/index.tsx"></script>
52
+ </body>
53
+ </html>
index.tsx ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import React from 'react';
7
+ import ReactDOM from 'react-dom/client';
8
+ import App from './App';
9
+
10
+ const rootElement = document.getElementById('root');
11
+ if (!rootElement) {
12
+ throw new Error("Could not find root element to mount to");
13
+ }
14
+
15
+ const root = ReactDOM.createRoot(rootElement);
16
+ root.render(
17
+ <React.StrictMode>
18
+ <App />
19
+ </React.StrictMode>
20
+ );
metadata.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "name": "Mostasheer",
3
+ "description": "An online clinic application featuring secure patient and doctor login, personalized dashboards, appointment management, financial tracking, medical history, an AI Health Assistant, and tools for doctor registration and clinic management.",
4
+ "requestFramePermissions": [],
5
+ "prompt": ""
6
+ }
package.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "mostasheer",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^19.1.1",
13
+ "@google/genai": "^0.14.0",
14
+ "react-dom": "^19.1.1",
15
+ "typeorm": "^0.3.26",
16
+ "@nestjs/common": "^11.1.6",
17
+ "@nestjs/typeorm": "^11.0.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^22.14.0",
21
+ "typescript": "~5.8.2",
22
+ "vite": "^6.2.0"
23
+ }
24
+ }
tsconfig.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "experimentalDecorators": true,
5
+ "useDefineForClassFields": false,
6
+ "module": "ESNext",
7
+ "lib": [
8
+ "ES2022",
9
+ "DOM",
10
+ "DOM.Iterable"
11
+ ],
12
+ "skipLibCheck": true,
13
+ "types": [
14
+ "node"
15
+ ],
16
+ "moduleResolution": "bundler",
17
+ "isolatedModules": true,
18
+ "moduleDetection": "force",
19
+ "allowJs": true,
20
+ "jsx": "react-jsx",
21
+ "paths": {
22
+ "@/*": [
23
+ "./*"
24
+ ]
25
+ },
26
+ "allowImportingTsExtensions": true,
27
+ "noEmit": true
28
+ }
29
+ }
types.ts ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ // --- CORE & ACCESS ---
7
+
8
+ export type View = 'dashboard' | 'appointments' | 'find-doctor' | 'health-assistant' | 'accounting' | 'doctor-registration' | 'clinic-management' | 'medical-history';
9
+
10
+ export type Role = 'owner' | 'doctor' | 'staff' | 'patient';
11
+
12
+ // New types for clinic settings
13
+ export interface OperatingHours {
14
+ monday: { active: boolean; start: string; end: string };
15
+ tuesday: { active: boolean; start: string; end: string };
16
+ wednesday: { active: boolean; start: string; end: string };
17
+ thursday: { active: boolean; start: string; end: string };
18
+ friday: { active: boolean; start: string; end: string };
19
+ saturday: { active: boolean; start: string; end: string };
20
+ sunday: { active: boolean; start: string; end: string };
21
+ }
22
+
23
+ export interface ClinicSettingsData {
24
+ operating_hours: OperatingHours;
25
+ online_booking: {
26
+ enabled: boolean;
27
+ auto_confirm: boolean;
28
+ min_booking_notice_hours: number;
29
+ cancellation_policy_hours: number;
30
+ };
31
+ financial: {
32
+ currency: string;
33
+ tax_rate_percent: number;
34
+ invoice_footer: string;
35
+ };
36
+ }
37
+
38
+
39
+ export interface Clinic {
40
+ id: string; // UUID
41
+ name: string;
42
+ owner_id?: string; // UUID of the owner user
43
+ created_at: string; // ISO 8601
44
+ // Add new detailed profile fields
45
+ address?: string;
46
+ contact_phone?: string;
47
+ contact_email?: string;
48
+ website?: string;
49
+ settings?: ClinicSettingsData;
50
+ }
51
+
52
+ export interface User {
53
+ id: string; // UUID
54
+ clinic_id: string; // Foreign Key to Clinic
55
+ email: string;
56
+ password_hash: string;
57
+ role: Role;
58
+ created_at: string; // ISO 8601
59
+ schedule_id?: string; // FK to Schedule
60
+ }
61
+
62
+ // --- CLINIC OPERATIONS ---
63
+
64
+ export interface Patient {
65
+ id: string; // UUID
66
+ clinic_id: string; // FK to Clinic
67
+ name: string;
68
+ dob?: string; // YYYY-MM-DD
69
+ gender?: string;
70
+ contact_info?: Record<string, string>; // JSONB
71
+ created_at: string; // ISO 8601
72
+ }
73
+
74
+ export interface Doctor {
75
+ id: string; // UUID
76
+ clinic_id: string; // FK to Clinic
77
+ name: string;
78
+ specialty?: string;
79
+ created_at: string; // ISO 8601
80
+ // Denormalized for UI convenience
81
+ photo?: string;
82
+ }
83
+
84
+ export interface Service {
85
+ id: string; // UUID
86
+ clinic_id: string; // FK to Clinic
87
+ name: string;
88
+ price: number;
89
+ duration_minutes: number;
90
+ currency?: string;
91
+ }
92
+
93
+ export type AppointmentStatus = 'scheduled' | 'completed' | 'canceled';
94
+
95
+ export interface Appointment {
96
+ id: string; // UUID
97
+ clinic_id: string; // FK to Clinic
98
+ patient_id: string; // FK to Patient
99
+ doctor_id: string; // FK to Doctor
100
+ service_id?: string; // FK to Service
101
+ start_time: string; // ISO 8601
102
+ status: AppointmentStatus;
103
+ }
104
+
105
+
106
+ // --- MEDICAL (EMR) ---
107
+
108
+ export interface Encounter {
109
+ id: string; // UUID
110
+ clinic_id: string; // FK to Clinic
111
+ patient_id: string; // FK to Patient
112
+ doctor_id: string; // FK to Doctor
113
+ appointment_id?: string; // FK to Appointment
114
+ notes?: string;
115
+ vitals?: Record<string, any>; // JSONB
116
+ created_at: string; // ISO 8601
117
+ }
118
+
119
+ export interface Problem {
120
+ encounter_id: string; // UUID
121
+ description: string;
122
+ }
123
+
124
+ export interface Allergy {
125
+ patient_id: string;
126
+ substance: string;
127
+ reaction?: string;
128
+ }
129
+
130
+ export interface Medication {
131
+ encounter_id: string; // UUID
132
+ drug_name: string;
133
+ dosage?: string;
134
+ instructions?: string;
135
+ }
136
+
137
+
138
+ // --- FINANCIALS ---
139
+
140
+ export type InvoiceStatus = 'draft' | 'issued' | 'paid' | 'canceled';
141
+
142
+ export interface InvoiceLine {
143
+ id: string; // UUID
144
+ invoice_id: string;
145
+ service_id?: string;
146
+ quantity: number;
147
+ price: number;
148
+ }
149
+
150
+ export interface Invoice {
151
+ id: string; // UUID
152
+ clinic_id: string; // FK to Clinic
153
+ patient_id: string; // FK to Patient
154
+ total: number;
155
+ status: InvoiceStatus;
156
+ issued_at: string; // ISO 8601
157
+ invoice_lines: InvoiceLine[]; // Denormalized for UI
158
+ }
159
+
160
+ export interface Payment {
161
+ id: string; // UUID
162
+ invoice_id: string; // FK to Invoice
163
+ amount: number;
164
+ method?: string;
165
+ paid_at: string; // ISO 8601
166
+ }
167
+
168
+ // --- UI SPECIFIC ---
169
+
170
+ // For doctor registration flow
171
+ export interface DoctorRegistrationData {
172
+ user: Partial<User>;
173
+ doctor: Partial<Doctor>;
174
+ }
175
+
176
+ // New type for schedule overrides
177
+ export interface DayOverride {
178
+ date: string; // YYYY-MM-DD
179
+ active: boolean;
180
+ start?: string; // HH:mm, required if active
181
+ end?: string; // HH:mm, required if active
182
+ }
183
+
184
+ // FIX: Define Schedule type for doctor schedule feature.
185
+ export interface Schedule {
186
+ id: string; // UUID
187
+ clinic_id: string; // FK to Clinic
188
+ appointment_length_minutes: number;
189
+ buffer_time_minutes: number;
190
+ overrides: DayOverride[]; // Replaces holidays for more flexibility
191
+ weekdays: {
192
+ monday: { active: boolean; start: string; end: string };
193
+ tuesday: { active: boolean; start: string; end: string };
194
+ wednesday: { active: boolean; start: string; end: string };
195
+ thursday: { active: boolean; start: string; end: string };
196
+ friday: { active: boolean; start: string; end: string };
197
+ saturday: { active: boolean; start: string; end: string };
198
+ sunday: { active: boolean; start: string; end: string };
199
+ };
200
+ }
vite.config.ts ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import path from 'path';
2
+ import { defineConfig, loadEnv } from 'vite';
3
+
4
+ export default defineConfig(({ mode }) => {
5
+ const env = loadEnv(mode, '.', '');
6
+ return {
7
+ define: {
8
+ 'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY),
9
+ 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY)
10
+ },
11
+ resolve: {
12
+ alias: {
13
+ '@': path.resolve(__dirname, '.'),
14
+ }
15
+ }
16
+ };
17
+ });