Kaballas commited on
Commit
90d0d5d
·
verified ·
1 Parent(s): 90467ca

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +437 -6
app.py CHANGED
@@ -1,9 +1,440 @@
1
- from fastapi import FastAPI
2
- from fastapi_mcp import FastApiMCP
3
 
4
- app = FastAPI()
 
5
 
6
- mcp = FastApiMCP(app)
7
 
8
- # Mount the MCP server directly to your FastAPI app
9
- mcp.mount()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastmcp import FastMCP
2
+ import requests
3
 
4
+ # Step 1: Create the server
5
+ mcp = FastMCP(name="MCP Server with Standardized Tools")
6
 
 
7
 
8
+ # Step 2: Add tools with proper naming and documentation
9
+ @mcp.tool
10
+ def calculate_sum(first_number: int, second_number: int) -> int:
11
+ """
12
+ This tool adds two integer numbers and returns their sum.
13
+
14
+ When to use:
15
+ - When simple mathematical addition is required
16
+ - As a basic calculator function
17
+
18
+ Limitations:
19
+ - Only handles integers, not floating point numbers
20
+ - No validation for integer overflow
21
+
22
+ Parameters:
23
+ - first_number: The first integer to be added
24
+ - second_number: The second integer to be added
25
+
26
+ Returns:
27
+ - The sum of the two provided integers
28
+ """
29
+ return first_number + second_number
30
+
31
+
32
+ @mcp.tool
33
+ def count_file_rows(file_path: str) -> int:
34
+ """
35
+ This tool counts the number of rows (lines) in a text file.
36
+
37
+ When to use:
38
+ - When you need to know the total number of lines in a file
39
+ - For analyzing file size in terms of line count
40
+ - Before processing files to understand their scope
41
+
42
+ Limitations:
43
+ - Only works with text files that can be read line by line
44
+ - Very large files may take time to process
45
+ - Binary files may produce unexpected results
46
+
47
+ Parameters:
48
+ - file_path: The absolute or relative path to the file to count rows for
49
+
50
+ Returns:
51
+ - The total number of rows (lines) in the file as an integer
52
+ """
53
+ try:
54
+ with open(file_path, 'r', encoding='utf-8') as file:
55
+ row_count = sum(1 for line in file)
56
+ return row_count
57
+ except FileNotFoundError:
58
+ raise ValueError(f"File not found: {file_path}")
59
+ except PermissionError:
60
+ raise ValueError(f"Permission denied accessing file: {file_path}")
61
+ except UnicodeDecodeError:
62
+ # Try with different encoding for non-UTF-8 files
63
+ try:
64
+ with open(file_path, 'r', encoding='latin-1') as file:
65
+ row_count = sum(1 for line in file)
66
+ return row_count
67
+ except Exception:
68
+ raise ValueError(f"Unable to read file (encoding issue): {file_path}")
69
+ except Exception as e:
70
+ raise ValueError(f"Error reading file: {e}")
71
+
72
+
73
+ # Step 3: Add a static resource (resources follow their own convention)
74
+ @mcp.resource("resource://config")
75
+ def get_config() -> dict:
76
+ """
77
+ Provides the application's configuration.
78
+
79
+ When to use:
80
+ - When configuration values are needed across the application
81
+
82
+ Returns:
83
+ - A dictionary containing version and author information
84
+ """
85
+ return {"version": "1.0", "author": "MyTeam"}
86
+
87
+
88
+ # Step 4: Add a resource template for dynamic content
89
+ @mcp.resource("greetings://{name}")
90
+ def personalized_greeting(name: str) -> str:
91
+ """
92
+ Generates a personalized greeting for the given name.
93
+
94
+ Parameters:
95
+ - name: The person's name to include in the greeting
96
+
97
+ Returns:
98
+ - A personalized greeting string
99
+ """
100
+ return f"Hello, {name}! Welcome to the MCP server."
101
+
102
+
103
+ @mcp.tool
104
+ def query_tax_advice(question: str) -> str:
105
+ """
106
+ This tool sends tax-related questions to the ATO API and returns the response.
107
+
108
+ When to use:
109
+ - When users need tax information or guidance
110
+ - For tax compliance queries
111
+
112
+ Limitations:
113
+ - Limited to Australian tax regulations
114
+ - Responses are informational only and not legal advice
115
+ - API rate limits apply (max 100 requests per hour)
116
+
117
+ Parameters:
118
+ - question: The tax-related question in natural language format
119
+
120
+ Returns:
121
+ - A string containing the ATO's response to the tax query
122
+ """
123
+ url = "https://kaballas-doe-work.hf.space/api/v1/openai/chat/completions"
124
+ headers = {
125
+ "accept": "*/*",
126
+ "Authorization": "Bearer PF9RE8T-7DFMFQ9-P14FTVJ-640YR2Y",
127
+ "Content-Type": "application/json",
128
+ }
129
+ data = {
130
+ "messages": [
131
+ {"role": "system", "content": "You are a helpful assistant"},
132
+ {"role": "user", "content": question},
133
+ ],
134
+ "model": "tax",
135
+ "stream": False,
136
+ "temperature": 0.7,
137
+ }
138
+ print("\n--- DEBUG ---")
139
+ print("User question:", question)
140
+ print("Request headers:", headers)
141
+ print("Request payload:", data)
142
+ try:
143
+ response = requests.post(url, headers=headers, json=data)
144
+ print("Response status code:", response.status_code)
145
+ print("Raw response:", response.text)
146
+ response.raise_for_status()
147
+ print("Response JSON:", response.json())
148
+ return str(response.json())
149
+ except Exception as e:
150
+ print("Exception occurred:", e)
151
+ return f"Error: {e}"
152
+
153
+
154
+ @mcp.tool
155
+ def generate_qa_plan(task: str, deadline: str) -> str:
156
+ """
157
+ This tool generates a structured QA plan based on the given task and deadline.
158
+
159
+ When to use:
160
+ - When creating test plans for software projects
161
+ - For establishing QA workflows with specific deadlines
162
+
163
+ Limitations:
164
+ - Plans are templates and may need customization
165
+ - Does not integrate with project management tools
166
+
167
+ Parameters:
168
+ - task: A description of the task requiring QA planning
169
+ - deadline: The date by which the QA process must be completed (format: YYYY-MM-DD)
170
+
171
+ Returns:
172
+ - A formatted string containing the QA plan with todo items
173
+ """
174
+ todo = f""" {task}
175
+
176
+ IMPORTANT: Recursively fetching links is crucial. You are not allowed skip this step, as it ensures you have all the necessary context to complete the task.
177
+
178
+ ### Read File Tool (`functions.read_file`)
179
+
180
+ 1. Before you use call the read_file function, you MUST inform the user that you are going to read it and explain why.
181
+
182
+ 2. Always read the entire file. You may read up to 2000 lines in a single read operation. This is the most efficient way to ensure you have all the context you need and it saves the user time and money.
183
+
184
+ 3. Unless a file has changed since the last time you read it.
185
+
186
+ IMPORTANT: Read the entire file. Failure to do so will result in a bad rating for you.
187
+ - [ ] IMPORTANT: Do **not** return control the user until you have **fully completed the user's entire request**. All items in your todo list MUST be checked off. Failure to do so will result in a bad rating for you.
188
+ - [ ] Validate if action is complete
189
+
190
+ """
191
+ return todo
192
+
193
+
194
+ @mcp.tool
195
+ def generate_python_code(task: str) -> str:
196
+ """
197
+ This tool generates Python code that accomplishes the described task.
198
+
199
+ When to use:
200
+ - When users need Python implementation examples
201
+ - For automating Python code generation based on requirements
202
+
203
+ Limitations:
204
+ - Generated code may require review and optimization
205
+ - Complex algorithms might not be optimally implemented
206
+ - Does not handle external dependencies or package installations
207
+
208
+ Parameters:
209
+ - task: A description of what the Python code should accomplish
210
+
211
+ Returns:
212
+ - A string containing the generated Python code with explanatory comments
213
+ """
214
+ url = "https://kaballas-doe-work.hf.space/api/v1/openai/chat/completions"
215
+ headers = {
216
+ "accept": "*/*",
217
+ "Authorization": "Bearer PF9RE8T-7DFMFQ9-P14FTVJ-640YR2Y",
218
+ "Content-Type": "application/json",
219
+ }
220
+ prompt = f"""Task is to write python code for the following task : '{task}' . """
221
+
222
+ data = {
223
+ "messages": [
224
+ {"role": "system", "content": "You are a helpful assistant"},
225
+ {"role": "user", "content": prompt},
226
+ ],
227
+ "model": "python",
228
+ "stream": False,
229
+ "temperature": 0.7,
230
+ }
231
+ try:
232
+ response = requests.post(url, headers=headers, json=data)
233
+ response.raise_for_status()
234
+ # Extract and return only the 'content' field from the 'assistant' message
235
+ return response.json()["choices"][0]["message"]["content"]
236
+ except Exception as e:
237
+ return f"Error: {e}"
238
+
239
+
240
+ @mcp.tool
241
+ def query_sap_knowledge(question: str) -> str:
242
+ """
243
+ This tool provides answers to SAP-related questions by querying a specialized knowledge model.
244
+
245
+ When to use:
246
+ - When users need information about SAP systems, modules, or best practices
247
+ - For troubleshooting SAP-specific issues
248
+
249
+ Limitations:
250
+ - Knowledge base may not cover the latest SAP updates
251
+ - Technical implementation details may vary by SAP version
252
+ - Some specialized modules may have limited coverage
253
+
254
+ Parameters:
255
+ - question: The SAP-related question in natural language format
256
+
257
+ Returns:
258
+ - A detailed response addressing the SAP question
259
+ """
260
+ url = "https://kaballas-doe-work.hf.space/api/v1/openai/chat/completions"
261
+ headers = {
262
+ "accept": "*/*",
263
+ "Authorization": "Bearer PF9RE8T-7DFMFQ9-P14FTVJ-640YR2Y",
264
+ "Content-Type": "application/json",
265
+ }
266
+ prompt = f"""Anwser the SAP related Question '{question}' . """
267
+
268
+ data = {
269
+ "messages": [
270
+ {"role": "system", "content": "You are a helpful assistant"},
271
+ {"role": "user", "content": prompt},
272
+ ],
273
+ "model": "sap",
274
+ "stream": False,
275
+ "temperature": 0.7,
276
+ }
277
+ try:
278
+ response = requests.post(url, headers=headers, json=data)
279
+ response.raise_for_status()
280
+ # Extract and return only the 'content' field from the 'assistant' message
281
+ return response.json()["choices"][0]["message"]["content"]
282
+ except Exception as e:
283
+ return f"Error: {e}"
284
+
285
+
286
+ @mcp.tool(
287
+ title="Task Analysis & Planning"
288
+ )
289
+ def interpret_task(task: str, deadline: str = "") -> str:
290
+ """
291
+ This tool analyzes a given task and generates a structured plan for completion.
292
+
293
+ When to use:
294
+ - As the first step in processing any user request
295
+ - For breaking down complex tasks into manageable steps
296
+
297
+ Limitations:
298
+ - Generated plans may need adjustment for specialized domains
299
+ - Cannot account for all edge cases in complex workflows
300
+ - Task interpretation quality depends on input clarity
301
+
302
+ Parameters:
303
+ - task: The description of the task to be analyzed and planned
304
+ - deadline: Optional deadline for task completion (format: YYYY-MM-DD)
305
+
306
+ Returns:
307
+ - A structured plan with steps to complete the task
308
+ """
309
+ url = "https://kaballas-doe-work.hf.space/api/v1/openai/chat/completions"
310
+
311
+ headers = {
312
+ "accept": "*/*",
313
+ "Authorization": "Bearer PF9RE8T-7DFMFQ9-P14FTVJ-640YR2Y",
314
+ "Content-Type": "application/json",
315
+ }
316
+
317
+ # Step 1: Send request to TaskInterpreter model
318
+ prompt = f"""INSTRUCTIONS: MCP TOOLING AND SCHEMA COMPLIANCE
319
+
320
+ ----------------------------------------
321
+ AVAILABLE TOOLS (DO NOT USE ANY OTHERS)
322
+ ----------------------------------------
323
+
324
+ {{
325
+ "tools": [
326
+ {{
327
+ "name": "calculate_sum",
328
+ "description": "Adds two integers and returns the result. Intended for basic integer addition tasks."
329
+ }},
330
+ {{
331
+ "name": "count_file_rows",
332
+ "description": "Counts the number of lines in a text file. Useful for gauging file size or preprocessing needs."
333
+ }},
334
+ {{
335
+ "name": "query_tax_advice",
336
+ "description": "Sends a natural language tax-related question to an ATO model and returns a response. Limited to Australian tax domain."
337
+ }},
338
+ {{
339
+ "name": "generate_qa_plan",
340
+ "description": "Generates a checklist-style QA plan for a task and deadline, including mandatory procedural steps."
341
+ }},
342
+ {{
343
+ "name": "generate_python_code",
344
+ "description": "Returns Python code that fulfills a user-described programming task. Output is raw code with inline comments."
345
+ }},
346
+ {{
347
+ "name": "query_sap_knowledge",
348
+ "description": "Answers SAP-related questions using a specialized model trained on SAP system knowledge."
349
+ }},
350
+ {{
351
+ "name": "interpret_task",
352
+ "description": "Analyzes a task and produces a structured execution plan. Often used as a first step before tool invocation."
353
+ }}
354
+ ],
355
+
356
+ }}
357
+
358
+ ----------------------------------------------------
359
+ MCP TOOLING RULES (ALL MUST BE FOLLOWED STRICTLY)
360
+ ----------------------------------------------------
361
+
362
+ 1. STRUCTURED RESULTS & SCHEMA COMPLIANCE
363
+
364
+ - All tool results must be structured JSON.
365
+ - If a tool defines an `outputSchema`, your output MUST conform exactly.
366
+ - Match all field names, data types, and required properties — no omissions, additions, or type mismatches.
367
+ - Clients and systems will validate JSON against this schema.
368
+
369
+ 2. TOOL NAMING CONVENTION
370
+
371
+ - Use only lowercase snake_case format: verb_noun
372
+ - The name must describe what the tool does and to what.
373
+ - DO NOT use vague names like `add`, `doTask`, or `Handler`.
374
+
375
+ Examples:
376
+ ✓ calculate_sum
377
+ ✓ query_tax_advice
378
+ ✓ interpret_task
379
+ ✗ Add
380
+ ✗ ATO_HELP
381
+ ✗ TaskInterpreter
382
+
383
+ 3. JSON OUTPUT REQUIREMENT
384
+
385
+ - Every tool result MUST return JSON only.
386
+ - DO NOT include markdown, comments, or explanatory text outside of the JSON object.
387
+ - Validate your output before returning it.
388
+
389
+ 4. EXISTING USER GUIDELINES (STILL IN EFFECT)
390
+
391
+ - Use step-by-step reasoning unless explicitly instructed not to.
392
+ - Prioritize correctness, clarity, and concise execution.
393
+ - Be brutally honest when asked — no sugarcoating or vague optimism.
394
+ - Always ask, “Am I missing something?” after completing a task.
395
+
396
+ ---------------------------------------------
397
+ POSSIBLE BLIND SPOTS / NEXT STEPS
398
+ ---------------------------------------------
399
+
400
+ - Ensure every tool has an explicit and validated output schema.
401
+ - Review tool naming for consistency with the required convention.
402
+ - Add schema validation to downstream consumers if not yet implemented.
403
+ - Eliminate or refactor any tools not listed in the approved set above.
404
+
405
+ No based on my instructions I need a tool for the following TASK :
406
+
407
+ **{task}
408
+
409
+ Return only the JSON object that represents the tool specification—no extra text, comments, or keys outside the schema.
410
+ """
411
+
412
+
413
+ print(prompt)
414
+ data = {
415
+ "messages": [
416
+ {"role": "system", "content": "All tool invocation results must be returned in JSON format only. Do not add extra text, commentary, or non‑JSON content"},
417
+ {"role": "user", "content": prompt},
418
+ ],
419
+ "model": "tools",
420
+ "stream": False,
421
+ "temperature": 0.3,
422
+ }
423
+
424
+ content = None
425
+ try:
426
+ response = requests.post(url, headers=headers, json=data)
427
+ response.raise_for_status()
428
+ content = response.json()["choices"][0]["message"]["content"]
429
+
430
+ print("-----------------")
431
+ print(content)
432
+ print("-----------------")
433
+ return content
434
+ except Exception as e:
435
+ return f"Error: {e}"
436
+
437
+
438
+ # Step 5: Make the server runnable
439
+ if __name__ == "__main__":
440
+ mcp.run(transport="http", host="0.0.0.0", port=7860, path="/mcp")