added more MCP commands
This commit is contained in:
BIN
LLM Integration/__pycache__/main.cpython-313.pyc
Normal file
BIN
LLM Integration/__pycache__/main.cpython-313.pyc
Normal file
Binary file not shown.
BIN
LLM Integration/__pycache__/model.cpython-313.pyc
Normal file
BIN
LLM Integration/__pycache__/model.cpython-313.pyc
Normal file
Binary file not shown.
BIN
LLM Integration/__pycache__/thingsboard.cpython-313.pyc
Normal file
BIN
LLM Integration/__pycache__/thingsboard.cpython-313.pyc
Normal file
Binary file not shown.
1
LLM Integration/examples/openapi-servers
Submodule
1
LLM Integration/examples/openapi-servers
Submodule
Submodule LLM Integration/examples/openapi-servers added at 2b7844d634
95
LLM Integration/main.py
Normal file
95
LLM Integration/main.py
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import json
|
||||||
|
import httpx
|
||||||
|
from fastapi import FastAPI, Request
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import Dict, Any
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
origins = ["*"]
|
||||||
|
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=origins,
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Load OpenAPI spec from IBM COS API
|
||||||
|
OPENAPI_URL = "https://thingsboard.cloud/v3/api-docs/thingsboard"
|
||||||
|
|
||||||
|
class ToolCallInput(BaseModel):
|
||||||
|
tool_name: str
|
||||||
|
input: Dict[str, Any]
|
||||||
|
|
||||||
|
# In-memory registry of tools
|
||||||
|
tool_registry = {}
|
||||||
|
|
||||||
|
async def fetch_openapi_spec():
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.get(OPENAPI_URL)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def generate_tools_from_openapi(openapi: Dict[str, Any]):
|
||||||
|
paths = openapi.get("paths", {})
|
||||||
|
if not paths:
|
||||||
|
raise ValueError(f"Path is empty or invalid for {service_name}")
|
||||||
|
|
||||||
|
for path, methods in paths.items():
|
||||||
|
for method, details in methods.items():
|
||||||
|
operation_id = details.get("operationId") or f"{method}_{path.replace('/', '_')}"
|
||||||
|
summary = details.get("summary", "")
|
||||||
|
|
||||||
|
# Create a basic tool function with a name and HTTP method
|
||||||
|
def make_tool(p, m):
|
||||||
|
async def tool_func(input_data):
|
||||||
|
region = input_data.get("region", "us-south")
|
||||||
|
headers = input_data.get("headers", {})
|
||||||
|
body = input_data.get("body", None)
|
||||||
|
params = input_data.get("params", None)
|
||||||
|
params = input_data.get("params", {})
|
||||||
|
formatted_path = p
|
||||||
|
for key, value in params.items():
|
||||||
|
formatted_path = formatted_path.replace(f"{{{key}}}", value)
|
||||||
|
url = f"https://thingsboard.cloud/v3{formatted_path}"
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
req = client.build_request(m.upper(), url, headers=headers, json=body, params=params)
|
||||||
|
res = await client.send(req)
|
||||||
|
return {"status_code": res.status_code, "body": res.text}
|
||||||
|
return tool_func
|
||||||
|
|
||||||
|
tool_registry[operation_id] = make_tool(path, method)
|
||||||
|
|
||||||
|
@app.post("/invoke")
|
||||||
|
async def invoke_tool(call: ToolCallInput):
|
||||||
|
tool_name = call.tool_name
|
||||||
|
input_data = call.input
|
||||||
|
print(input_data)
|
||||||
|
if tool_name not in tool_registry:
|
||||||
|
return JSONResponse(status_code=404, content={"error": "Tool not found"})
|
||||||
|
|
||||||
|
tool_func = tool_registry[tool_name]
|
||||||
|
try:
|
||||||
|
result = await tool_func(input_data)
|
||||||
|
return JSONResponse(content={"output": result})
|
||||||
|
except Exception as e:
|
||||||
|
return JSONResponse(status_code=500, content={"error": str(e)})
|
||||||
|
|
||||||
|
@app.get("/tools")
|
||||||
|
async def list_tools():
|
||||||
|
return JSONResponse(content={"tools": list(tool_registry.keys())})
|
||||||
|
|
||||||
|
@app.on_event("startup")
|
||||||
|
async def startup():
|
||||||
|
openapi = await fetch_openapi_spec()
|
||||||
|
generate_tools_from_openapi(openapi)
|
||||||
|
print(f"Registered tools: {list(tool_registry.keys())}")
|
||||||
10357
LLM Integration/model.py
Normal file
10357
LLM Integration/model.py
Normal file
File diff suppressed because one or more lines are too long
113
LLM Integration/thingsboard.py
Normal file
113
LLM Integration/thingsboard.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
from model import *
|
||||||
|
from fastapi import FastAPI, HTTPException, Body
|
||||||
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from typing import Literal
|
||||||
|
import requests, json
|
||||||
|
from datetime import datetime as dt
|
||||||
|
from datetime import timedelta as td
|
||||||
|
app = FastAPI(
|
||||||
|
title="Thingsboard API",
|
||||||
|
version="1.0.0",
|
||||||
|
description="Provides secure access to Thingsboard API",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
origins = ["*"]
|
||||||
|
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=origins,
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def getJWT():
|
||||||
|
response = requests.post(url_base + 'auth/login', headers=headers,data=credentials)
|
||||||
|
token = response.json()
|
||||||
|
headers["X-Authorization"] = "Bearer " + token['token']
|
||||||
|
|
||||||
|
@app.get("/customers", response_model=List[Customer])
|
||||||
|
def getCustomers(page: int = 0, pageSize: int = 10):
|
||||||
|
"""
|
||||||
|
Returns a list of customers from Thingsboard API.
|
||||||
|
"""
|
||||||
|
response = requests.get(
|
||||||
|
url_base + f"customers?page={page}&pageSize={pageSize}", headers=headers)
|
||||||
|
#print(json.dumps(response.json(), indent=4))
|
||||||
|
customers = []
|
||||||
|
customers = response.json()['data']
|
||||||
|
while(response.json()["hasNext"]):
|
||||||
|
page += 1
|
||||||
|
response = requests.get(url_base + f"customers?page={page}&pageSize={pageSize}", headers=headers)
|
||||||
|
customers += response.json()['data']
|
||||||
|
#print(customers)
|
||||||
|
return customers
|
||||||
|
|
||||||
|
@app.get("/customerNames", response_model=List[str])
|
||||||
|
def getCustomerNames(page=0, pageSize=10):
|
||||||
|
"""
|
||||||
|
Returns a list of customer names from Thingsboard API.
|
||||||
|
"""
|
||||||
|
customers = getCustomers(page=0, pageSize=10)
|
||||||
|
names = []
|
||||||
|
for c in customers:
|
||||||
|
names.append(c['name'])
|
||||||
|
#print(names)
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/telemetry", response_model=dict)
|
||||||
|
def getTelemetry(startTs, endTs, keys, eType, deviceId):
|
||||||
|
"""
|
||||||
|
Returns a list of telemetry data from Thingsboard API.
|
||||||
|
parameters:
|
||||||
|
startTs: Timestamp of the start time for the data in milliseconds.
|
||||||
|
endTs: Timestamp of the end time for the data in milliseconds.
|
||||||
|
keys: List of attribute keys to retrieve (e.g., temperature,humidity,etc.).
|
||||||
|
eType: Type of entity (e.g., 'ASSET', 'DEVICE').
|
||||||
|
deviceId: ID of the device as a UUID
|
||||||
|
"""
|
||||||
|
if(not keys):
|
||||||
|
keys = ["temperature", "humidity"]
|
||||||
|
if(not startTs):
|
||||||
|
#set startTs to time from 1 hour ago and put it in timestamp format with milliseconds
|
||||||
|
startTs = dt.timestamp(dt.now() - td(hours=1)) * 1000
|
||||||
|
if(not endTs):
|
||||||
|
#set endTs to time from now and put it in timestamp format with milliseconds
|
||||||
|
endTs = dt.timestamp(dt.now()) * 1000
|
||||||
|
telemetry = requests.get(
|
||||||
|
url_base + f"plugins/telemetry/{eType}/{deviceId}/values/timeseries?startTs={startTs}&endTs={endTs}&keys={keys}", headers=headers)
|
||||||
|
print(telemetry.json())
|
||||||
|
return telemetry.json()
|
||||||
|
|
||||||
|
@app.get("/deviceIdByName", response_model=dict)
|
||||||
|
def getDeviceByName(textSearch: str, deviceType: str = None, sortProperty: str = None, sortOrder: str = "ASC",page: int = 0, pageSize: int = 10):
|
||||||
|
"""
|
||||||
|
Returns a dictionary with the device ID (as a UUID) of a device with a given name in the textSearch param
|
||||||
|
parameters:
|
||||||
|
deviceType: optional parameter to specify the device type for search
|
||||||
|
textSearch: the string or substring of the name of the device being searched for
|
||||||
|
sortProperty: optional parameter to specify the property to sort by can be one of the following [createdTime, name, deviceProfileName, label, customerTitle]
|
||||||
|
sortOrder: optional parameter to specify is ascending or descending order [ASC, DESC]
|
||||||
|
page: the page of results to acquire default is set to 0 to get the first page
|
||||||
|
pageSize: the number of results per page
|
||||||
|
"""
|
||||||
|
response = requests.get(url_base + f"user/devices?page={page}&pageSize={pageSize}&textSearch={textSearch}", headers=headers)
|
||||||
|
#print(response.url)
|
||||||
|
#print(response.request)
|
||||||
|
#print(json.dumps(response.json(),indent=4))
|
||||||
|
devices = response.json()["data"]
|
||||||
|
device = {textSearch: devices[0]["id"]["id"]}
|
||||||
|
return device
|
||||||
|
headers = {"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json"}
|
||||||
|
username = "nmelone@henry-pump.com"
|
||||||
|
password = "gzU6$26v42mU%3jDzTJf"
|
||||||
|
domain = "thingsboard.cloud"
|
||||||
|
credentials = json.dumps(
|
||||||
|
{"username": f"{username}", "password": f"{password}"})
|
||||||
|
url_base = f"https://{domain}/api/"
|
||||||
|
getJWT()
|
||||||
|
#print(headers)
|
||||||
129301
LLM Integration/thingsboardAPI.json
Normal file
129301
LLM Integration/thingsboardAPI.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user