We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/motebus/ultra-mcp-ss'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
from fastapi import FastAPI, Depends, HTTPException, Response, Query
from pydantic import BaseModel, Field
import os
import urllib.parse
import httpx
from fastapi_mcp import FastApiMCP
from dotenv import load_dotenv
app = FastAPI(title="ultra-mcp-ss")
load_dotenv()
YOUTUBE_API_KEY = os.environ.get("YOUTUBE_API_KEY")
YOUTUBE_API_URL = "https://www.googleapis.com/youtube/v3/search"
SMARTSCREEN_API_URL = "https://smartscreen.tv/api"
SMARTSCREEN_SERVICE_TOKEN = os.environ.get("SS_SERVICE_TOKEN")
async def search_youtube_video(query: str) -> str | None:
"""
Searches YouTube for the most relevant video and returns its ID.
Returns None if no video is found or an error occurs.
"""
if not YOUTUBE_API_KEY:
print("Error: YOUTUBE_API_KEY environment variable not set.")
return None
encoded_query = urllib.parse.quote_plus(query)
params = {
"part": "snippet",
"q": encoded_query,
"key": YOUTUBE_API_KEY,
"type": "video",
"maxResults": 1,
"order": "relevance"
}
try:
async with httpx.AsyncClient() as client:
response = await client.get(YOUTUBE_API_URL, params=params)
response.raise_for_status() # Raise an exception for 4xx or 5xx status codes
data = response.json()
if data.get("items"):
# Safely get the videoId
video_id = data["items"][0].get("id", {}).get("videoId")
return video_id
else:
# No results found for the query
return None
except httpx.RequestError as exc:
print(f"An error occurred while requesting {exc.request.url!r}: {exc}")
return None
except httpx.HTTPStatusError as exc:
print(f"Error response {exc.response.status_code} while requesting {exc.request.url!r}.")
print(f"Response body: {exc.response.text}")
return None
except Exception as e:
print(f"An unexpected error occurred: {e}")
return None
# Pydantic models for input
class DropRequest(BaseModel):
display: str
item: str # the item to drop
x: int = 0 # coordinate (if applicable)
y: int = 0 # coordinate (if applicable)
class NotifyRequest(BaseModel):
display: str
message: str
priority: str# = Field(default="normal")
class ToastRequest(BaseModel):
display: str
message: str
heading: str
icon: str
transition: str
duration: str = "5"
class MarqueeRequest(BaseModel):
display: str
message: str
duration: str = "30"
color: str
size: str = "3"
bgcolor: str
class TextRequest(BaseModel):
display: str
message: str
duration: str = "30"
color: str
size: str = "3"
bgcolor: str
align: str
frame: str
animate: str
aniduration: str = "2"
class AppRequest(BaseModel):
display: str
url: str
duration: str = "0"
frame: str
class TouchRequest(BaseModel):
display: str
option: str
value: str# = ""
class StatusRequest(BaseModel):
display: str
option: str
value: str# = ""
class DjRequest(BaseModel):
display: str
option: str
value: str
class SmartScreenClient:
"""
Client for calling the real SmartScreen API.
It sends a POST request to the SmartScreen API endpoint with a payload containing:
- 'to': { "ddn": "yview" } (using yview as the destination target)
- 'data': (a command JSON as specified)
It uses httpx in async mode.
"""
def __init__(self):
self.api_url = SMARTSCREEN_API_URL
self.token = SMARTSCREEN_SERVICE_TOKEN
async def drop(self, item: str, display: str, x: int, y: int) -> bool:
# Construct the command payload for "drop"
command = {
"cmd": "drop",
"type": "url",
"src": [item], # Use the passed URL instead of hardcoded one
"duration": "0", # 0 means play to end
"frame": "main",
"animate": "fade",
"aniduration": "2",
"pmode": "loop",
"bgcolor": "white"
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.token}" # Use class variable instead of hardcoded token
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
# Check for HTTP success (200 OK)
if response.status_code != 200:
print(f"SmartScreen drop failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen drop error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def notify(self, message: str, display: str, priority: str) -> bool:
# Construct the command payload for "notify"
command = {
"cmd": "notify",
"msg": message,
"duration": "30", # set default duration; could be a parameter in the future
"color": "blue",
"size": "3"
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen notify failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen notify error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def toast(self, message: str, display: str, heading: str, icon: str, transition: str, duration: str) -> bool:
# Construct the command payload for "toast"
command = {
"cmd": "toast",
"msg": message,
"heading": heading,
"icon": icon,
"transition": transition,
"duration": duration
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen toast failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen toast error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def marquee(self, message: str, display: str, duration: str, color: str, size: str, bgcolor: str) -> bool:
# Construct the command payload for "marquee"
command = {
"cmd": "marquee",
"msg": message,
"duration": duration,
"color": color,
"size": size,
"bgcolor": bgcolor
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen marquee failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen marquee error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def text(self, message: str, display: str, duration: str, color: str, size: str,
bgcolor: str, align: str, frame: str, animate: str, aniduration: str) -> bool:
# Construct the command payload for "text"
command = {
"cmd": "text",
"msg": message,
"duration": duration,
"color": color,
"size": size,
"bgcolor": bgcolor,
"align": align,
"frame": frame,
"animate": animate,
"aniduration": aniduration
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen text failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen text error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def app(self, url: str, display: str, duration: str, frame: str) -> bool:
# Construct the command payload for "app"
command = {
"cmd": "app",
"url": url,
"duration": duration,
"frame": frame
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen app failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen app error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def touch(self, option: str, display: str, value: str) -> bool:
# Construct the command payload for "touch"
command = {
"cmd": "touch",
"option": option,
"value": value
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen touch failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen touch error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def status(self, option: str, display: str, value: str) -> bool:
# Construct the command payload for "status"
command = {
"cmd": "status",
"option": option,
"value": value
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen status failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen status error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
async def dj(self, option: str, display: str, value: str) -> bool:
# Construct the command payload for "dj"
command = {
"cmd": "dj",
"option": option,
"value": value
}
payload = {
"to": {"name": display},
"data": command
}
headers = {
"Authorization": f"Bearer {self.token}"
}
async with httpx.AsyncClient() as client:
response = await client.post(self.api_url, headers=headers, json=payload)
if response.status_code != 200:
print(f"SmartScreen dj failed: {response.text}")
return False
result = response.json()
if result.get("ErrCode", -1) != 0:
print(f"SmartScreen dj error: {result.get('ErrMsg', 'Unknown error')}")
return False
return True
# Create an instance of our SmartScreen client.
smartscreen_client = SmartScreenClient()
@app.head("/mcp")
async def mcp_head():
return Response(status_code=200)
@app.get("/search-youtube", summary="Search YouTube Video", response_description="URL of the most relevant YouTube video")
async def get_youtube_video_link(
query: str = Query(..., description="The search query for YouTube.")
):
"""
Accepts a search query and returns the YouTube link
for the most relevant video found.
"""
if not YOUTUBE_API_KEY:
raise HTTPException(status_code=500, detail="API key configuration error. Please check server logs.")
video_id = await search_youtube_video(query)
if video_id:
# Construct the standard YouTube URL
video_url = f"https://www.youtube.com/watch?v={video_id}"
return {"video_url": video_url}
else:
# Handles cases where search failed or no results were found
raise HTTPException(status_code=404, detail=f"No relevant YouTube video found for query: '{query}'")
@app.get("/test", tags=["test"])
async def test_endpoint():
"""
Test endpoint to check if the API is running.
"""
return {"message": "My name is MCP Vincent, and I am here to help you."}
# API endpoint for drop command
@app.post("/drop")
async def drop_item(request: DropRequest):
"""
Drop an item onto the SmartScreen at the specified coordinates.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'drop' tool.
What it does:
Displays an image or video on the screen.
Why/When to use:
Use it whenever you want to show media content—like a video, slideshow, or static image—on a particular screen area.
Key options:
• type: "url" (URLs for images/videos)
• src: one or more URLs of the media files
• duration: how long to display/play (0 = play to end)
• frame: on which screen area (e.g., main, t1, t2)
• animate: animation style (fade, slide, etc.)
• pmode: playback mode (“loop” or “random”)
"""
success = await smartscreen_client.drop(item=request.item,x=request.x,y=request.y,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to drop item")
return {"message": "Item dropped successfully", "item": request.item, "x": request.x, "y": request.y}
# API endpoint for notify command
@app.post("/notify")
async def notify_user(request: NotifyRequest):
"""
Send a notification message to the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'notify' tool.
What it does:
Shows a notification banner containing simple text.
Why/When to use:
If you want to display a short message or alert without interrupting the main screen content.
Key options:
• msg: notification text
• duration: how long to display
• color, size: appearance settings for text
"""
success = await smartscreen_client.notify(message=request.message,priority=request.priority,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to send notification")
return {"message": "Notification sent successfully", "notification": request.message}
# New API endpoints for additional SmartScreen commands
@app.post("/toast")
async def toast_message(request: ToastRequest):
"""
Display a toast message on the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'toast' tool.
What it does:
Shows a popup message with optional heading, icon, and transition effects.
Why/When to use:
Ideal for quick, transient notes (toasts) that appear and then disappear without disturbing the main content.
Key options:
• msg: main text content
• heading: optional title/heading
• icon: can be info, warning, error, or success
• transition: how it appears (plain, fade, slide)
• duration: how long the toast stays visible
"""
success = await smartscreen_client.toast(message=request.message,heading=request.heading,
icon=request.icon,transition=request.transition,duration=request.duration,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to show toast message")
return {"message": "Toast displayed successfully", "toast": request.message}
@app.post("/marquee")
async def marquee_text(request: MarqueeRequest):
"""
Display scrolling marquee text on the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'marquee' tool.
What it does:
Displays scrolling text across the screen.
Why/When to use:
Useful for announcements or continuously running messages (e.g., news ticker, short updates) in a marquee format.
Key options:
• msg: marquee text
• duration: how long to keep scrolling
• color, size: text styling
• bgcolor: background color
"""
success = await smartscreen_client.marquee(message=request.message,duration=request.duration,
color=request.color,size=request.size,bgcolor=request.bgcolor,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to show marquee text")
return {"message": "Marquee displayed successfully", "marquee": request.message}
@app.post("/text")
async def display_text(request: TextRequest):
"""
Display text on the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'text' tool.
What it does:
Shows a static block of text with customizable appearance and alignment.
Why/When to use:
Use to render text that remains on the screen for a set duration, possibly in a specific frame or layout region.
Key options:
• msg: text to display
• duration: display length (seconds)
• color, size, bgcolor: styling
• align: left, center, or right
• animate: how text appears (fade, slide, etc.)
"""
success = await smartscreen_client.text(message=request.message,duration=request.duration,
color=request.color,size=request.size,bgcolor=request.bgcolor,
align=request.align,frame=request.frame,animate=request.animate,
aniduration=request.aniduration,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to show text")
return {"message": "Text displayed successfully", "text": request.message}
@app.post("/app")
async def launch_app(request: AppRequest):
"""
Launch a web application on the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'app' tool.
What it does:
Loads and displays a webpage within a specified frame.
Why/When to use:
If you need to embed a browser view or show dynamic web content on the SmartScreen.
Key options:
• url: the webpage’s URL
• duration: how long to display (0 = indefinite)
• frame: target screen region
"""
success = await smartscreen_client.app(url=request.url,duration=request.duration,frame=request.frame,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to launch app")
return {"message": "App launched successfully", "url": request.url}
@app.post("/touch")
async def touch_command(request: TouchRequest):
"""
Send a touch command to control the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'touch' tool.
What it does:
Sends control commands like play/pause, next/previous, volume up/down, or console commands.
Why/When to use:
Ideal for interactive control of media playback or SmartScreen settings without reloading the main content.
Key options:
• option: specifies the control action (playnext, mute, console, etc.)
• value: additional parameter if needed (e.g., console sub-command)
"""
success = await smartscreen_client.touch(option=request.option,value=request.value,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to execute touch command")
return {"message": "Touch command executed successfully", "option": request.option, "value": request.value}
@app.post("/status")
async def status_command(request: StatusRequest):
"""
Get or set status information on the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'status' tool.
What it does:
Requests status information from the SmartScreen, such as version, frame usage, or device info.
Why/When to use:
If you need to check what’s currently playing, or retrieve system details (e.g., debugging, system health checks).
Key options:
• option: type of status (frame, ver, devinfo)
• value: additional context (like which frame)
"""
success = await smartscreen_client.status(option=request.option,value=request.value,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to execute status command")
return {"message": "Status command executed successfully", "option": request.option, "value": request.value}
@app.post("/dj")
async def dj_command(request: DjRequest):
"""
Execute a DJ command on the SmartScreen.
MCP Tool Exposure: This endpoint is exposed via MCP as the 'dj' tool.
What it does:
Manages higher-level features like scheduling commands, changing startup behavior, toggling kiosk mode, or updating the logo.
Why/When to use:
When you want to schedule commands (to run at startup or a specific time), change the logo, or restart the SmartScreen service.
Key options:
• logo: sets a new logo URL
• kiosk: toggles kiosk mode on/off
• startcmd/schcmd: schedule commands for startup or specific time triggers
• restart: restarts the SmartScreen.
"""
success = await smartscreen_client.dj(option=request.option, value=request.value,display=request.display)
if not success:
raise HTTPException(status_code=500, detail="Failed to execute DJ command")
return {"message": "DJ command executed successfully", "option": request.option, "value": request.value}
mcp = FastApiMCP(
app,
name="ultra-mcp-ss"
)
mcp.mount() # mounts at '/mcp' by default
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)