Das Model Context Protocol (MCP) entwickelt sich rasant zu einem der meistdiskutierten Konzepte in der KI-Welt. Obwohl es noch relativ neu ist, hat es bereits die Aufmerksamkeit von Entwicklern und großen Technologieunternehmen auf sich gezogen.
MCP wurde von Anthropic entwickelt und ist ein offenes Standardprotokoll, ähnlich wie andere Protokolle wie HTTP. Während HTTP jedoch dazu dient, Benutzer über einen Server und einen Webbrowser (oder HTTP-Client) mit Ressourcen zu verbinden, ist MCP darauf ausgelegt, Large Language Models (LLMs) mit externen Tools und Daten zu verbinden.
Angenommen, du hast einen Chatbot und möchtest, dass er auf GitHub zugreifen kann. Du möchtest, dass deine Benutzer den Chatbot nutzen können, um Issues zu erstellen, Issues zu schließen, Kommentare hinzuzufügen oder bestehende Pull-Requests anzusehen. Damit dein Chatbot all diese Aktionen ausführen kann, benötigt er Zugriff auf Tools.
Hier kommt ein MCP-Server ins Spiel.
Der MCP-Server hostet mehrere Tools, die der Chatbot mithilfe seines internen LLM aufrufen kann, um auf diese Fähigkeiten zuzugreifen. Im Fall von GitHub können wir den offiziellen GitHub MCP-Server verwenden, um alle oben genannten Aufgaben auszuführen.
In diesem Artikel werden wir einen MCP-Server mit der Novita-API erstellen. Mit diesem MCP-Server kann jede Anwendung, die das MCP-Protokoll unterstützt, auf alle auf Novita verfügbaren LLMs zugreifen, Bilder generieren, Videos erstellen und Sprachsynthese durchführen.
Die MCP-Architektur verstehen

Die MCP-Architektur [Quelle]
Die MCP-Architektur ähnelt einem typischen Client-Server-Setup. Sie besteht aus vier wichtigen Komponenten:
- MCP-Client
- MCP-Server
- MCP-Transporte
- MCP-Host
MCP-Client
Der MCP-Client dient als Kommunikationsgateway zwischen der KI-Anwendung und einem MCP-Server. Sobald diese Kommunikation hergestellt ist, kann die Anwendung auf alle Tools und Ressourcen zugreifen, die der Server bereitstellt.
MCP-Server
Der MCP-Server hostet alle Tools und Daten, die der Client der KI-Anwendung bereitstellen kann. Er hostet Folgendes:
- Tools
- Ressourcen
- Prompts
Tools
Tools bieten LLMs externe Fähigkeiten, die sie normalerweise nicht hätten, wie z. B. die Möglichkeit, die Uhrzeit zu erfragen, eine Datenbank zu aktualisieren und auszulesen, das Wetter abzurufen und mehr. Diese Tools sind im Grunde programmiererdefinierte Funktionen, die aufgerufen werden können.
Ein MCP-Server kann mehrere Tools hosten. Diese Tools ermöglichen es dem LLM, als Agent zu fungieren, aufgrund der Aktionen, die es ausführen kann.
Tools werden vom Agenten verwaltet und können während der Nutzung eine optionale menschliche Aufsicht beinhalten. Sie ähneln POST-Anfragen im HTTP-Protokoll, da sie Seiteneffekte auslösen.
Ressourcen
Ressourcen sind schreibgeschützte Informationen, die der KI-Anwendung Daten zur Verfügung stellen. Sie sind analog zu HTTP-GET-Anfragen, da sie keine Seiteneffekte verursachen sollen. Ressourcen sollen von der Anwendung verwaltet werden, die entscheidet, wie Benutzer oder der Agent mit ihnen interagieren. Beispiele für Ressourcen sind Dateiinhalte, API-Antworten und Datensätze aus Datenbanken.
Prompts
MCP-Server können Prompt-Vorlagen hosten. Diese Prompts ermöglichen es dem Benutzer, Prompts vom MCP-Server abzurufen, die dann in der KI-Anwendung verwendet werden können. Prompts werden vom Benutzer verwaltet, der entscheidet, welche Prompts dem Agenten bereitgestellt werden.
All diese Komponenten bilden den MCP-Server. In diesem Artikel werden wir nur Tools implementieren, da sie der am häufigsten genutzte Teil des MCP-Servers sind.
MCP-Transport
MCP-Transport bezeichnet die Methode, mit der der MCP-Client mit dem MCP-Server kommuniziert. Diese Kommunikation kann lokal erfolgen, wenn sowohl Client als auch Server auf demselben Rechner laufen, oder remote, wenn sie sich auf verschiedenen Geräten befinden. MCP unterstützt derzeit zwei Haupttransportmechanismen:
- STDIO: In diesem Modus laufen MCP-Server und Client auf demselben Rechner und kommunizieren über Standardeingabe und -ausgabe.
- SSE: In diesem Modus läuft der MCP-Server über HTTP. HTTP POST wird verwendet, um Nachrichten an den Server zu senden, während Server-Sent Events verwendet werden, um Nachrichten vom Server an den Client zu senden.
- Streamable HTTP: Dieser Modus verwendet ebenfalls HTTP, setzt aber auf HTTP-GET- und POST-Anfragen. Er greift nur dann auf SSE zurück, wenn mehrere Nachrichten vom Server an den Client gestreamt werden müssen.
Standardeingabe/-ausgabe

MCP-Transport mittels STDIO [Quelle]
MCP-Transport mittels STDIO [Quelle]
MCP-Client und -Server können über Standardeingabe und -ausgabe (STDIO) kommunizieren. Bei Verwendung von STDIO laufen sowohl Client als auch Server auf demselben Rechner. Der Client schreibt alle Anfragen in stdin, während der Server die Antwort in stdout schreibt.
Streamable HTTP

MCP-Transport mittels Streamable HTTP [Quelle]
Streamable HTTP ermöglicht die Kommunikation von MCP-Client und -Server über HTTP. Es verwendet die HTTP-POST-Methode, um Anfragen vom Client zu senden und Antworten vom Server zu empfangen. Bei Bedarf kann es optional auf Server-Sent Events (SSE) umschalten, um Nachrichten vom Server zum Client zu streamen.
Streamable HTTP eignet sich gut für die Remote-Kommunikation zwischen Client und Server und dient als Ersatz für den veralteten MCP-SSE-Transport.
MCP-HOST
Wo sich MCP von einer typischen Client-Server-Architektur unterscheidet, ist die Rolle des Hosts. Die MCP-Spezifikation definiert ihn als Client-Host-Server-Architektur. Dies liegt daran, dass Client und Host das Frontend der Architektur bilden. Der MCP-Host besteht aus zwei wichtigen Komponenten:
- Dem/den MCP-Client(s)
- Einem Large Language Model
Die Aufgabe des MCP-Clients besteht darin, Tools, Ressourcen und Prompts, die das LLM benötigt, vom Server abzurufen. Sobald die Ressourcen gesammelt wurden, werden sie in den Kontext des Modells eingefügt. Ein einzelner MCP-Host kann mehrere Clients haben, die jeweils mit einem eigenen MCP-Server verbunden sind.
Der MCP-Host kann auch als die Anwendung betrachtet werden, an der der Benutzer arbeitet, die möglicherweise andere Funktionen ausführt. Beispielsweise ist Claude Desktop ein MCP-Host, der als Chatbot fungiert, Cursor ist ein MCP-Host, der auch als IDE dient, und Claude Code ist ein MCP-Host, der als KI-Codierungsagent konzipiert ist.
Arbeiten mit einem MCP-Server
Bevor wir mit dem Bau unseres MCP-Servers beginnen, sehen wir uns an, wie wir mit einem vorhandenen MCP-Server arbeiten können. Wir verwenden das Python MCP SDK, um mit dem novita-mcp-server zu interagieren.
Zum Zeitpunkt der Erstellung dieses Artikels bietet der novita-mcp-server die folgenden Tools:
- Ein Tool zum Auflisten aller Novita-Cluster
- Ein Tool zum Auflisten der Novita-GPU-Instanzprodukte
- Ein Tool zum Auflisten aller laufenden GPU-Instanzen
- Ein Tool zum Erstellen neuer GPU-Instanzen
Lassen Sie uns dies bestätigen, indem wir ein einfaches Skript schreiben, das eine Verbindung zum MCP-Server über STDIO herstellt und alle auf dem Server verfügbaren Tools auflistet.
Installieren Sie zunächst das MCP SDK: pip install “mcp[cli]”
Nachdem wir das SDK installiert haben, erstellen wir eine Datei namens client.py. Dann importieren wir alle erforderlichen Module:
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
import os
Dann verwenden wir die StdioServerParameters, um unsere Parameter zum Starten unseres MCP-Servers über stdio festzulegen. Der novita-mcp-server ist in Node.js implementiert, daher müssen wir ihn mit dem Befehl npx ausführen. Außerdem müssen wir unseren Novita-API-Schlüssel in der Umgebungsvariable NOVITA_API_KEY speichern.
# Serverparameter für die STDIO-Verbindung erstellen
server_params = StdioServerParameters(
command="npx",
args=["-y", "@novitalabs/novita-mcp-server"],
env={"NOVITA_API_KEY": os.environ["NOVITA_API_KEY"]},
)
Als Nächstes erstellen wir eine asynchrone Funktion. Innerhalb der Funktion übergeben wir die Serverparameter an die stdio_client-Funktion, die einen Kontext erstellt, der Lese- und Schreibströme zurückgibt. Diese Ströme ermöglichen es uns, von stdio zu lesen bzw. in stdio zu schreiben.
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Verbindung initialisieren
await session.initialize()
# Verfügbare Tools auflisten
tools = await session.list_tools()
print("Verfügbare Tools:", tools)
Diese Ströme werden dann verwendet, um mit der ClientSession-Klasse eine Sitzung zu erstellen. Sobald wir unsere Sitzung erstellt haben, können wir sie initialisieren und dann alle Tools auf dem Server auflisten.
Um dieses Programm auszuführen, müssen wir nur die asyncio-Bibliothek verwenden, um die run-Funktion aufzurufen. Hier ist der vollständige Code:
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
import os
# Serverparameter für die STDIO-Verbindung erstellen
server_params = StdioServerParameters(
command="npx",
args=["-y", "@novitalabs/novita-mcp-server"],
env={"NOVITA_API_KEY": os.environ["NOVITA_API_KEY"]},
)
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Verbindung initialisieren
await session.initialize()
# Verfügbare Tools auflisten
tools = await session.list_tools()
print("Verfügbare Tools:", tools)
if __name__ == "__main__":
import asyncio
asyncio.run(run())
Durch Ausführen des Skripts können wir alle Tools des Novita MCP-Servers sehen.
Dieses Beispiel zeigt, wie Sie den MCP-Client verwenden können. Wir könnten diesem Beispiel ein LLM hinzufügen und es effektiv in einen Host verwandeln, aber das ist nicht der Schwerpunkt dieses Tutorials. Ziel ist es, einen MCP-Server zu bauen.
Erstellen eines MCP-Servers mit FastMCP
Im Python MCP SDK gibt es zwei Möglichkeiten, MCP-Server zu bauen. Eine Methode ist die Verwendung des Low-Level-Servers, die andere ist die Verwendung von FastMCP. FastMCP ist eine Klasse im MCP Python SDK, die von FastAPI inspiriert ist, um die Erstellung von MCP-Servern zu erleichtern.
Lassen Sie uns FastMCP verwenden, um unseren MCP-Server zu erstellen. Bevor wir beginnen, überlegen wir uns die Funktionalitäten unseres MCP-Servers. Der aktuelle Novita MCP-Server implementiert nur Tools, die sich mit der GPU-Verwaltung befassen. Versuchen wir, einen Server rund um die Novita-API zu bauen, der über die GPU-Verwaltung hinausgeht.
Stattdessen bauen wir einen MCP-Server, der Zugriff auf die Modelle der Novita-Plattform bietet. Unser MCP-Server wird nur Tools haben, keine Ressourcen oder Prompts. Hier ist eine Liste der Tools, die der Server haben wird:
- list_models: Dieses Tool listet alle Large Language Models auf der Novita-Plattform auf.
- get_model: Dieses Tool ruft ein bestimmtes Large Language Model ab und verwendet es.
- text2image: Dieses Tool generiert Bilder aus einem gegebenen Prompt.
- task_result: Dieses Tool wird verwendet, um den Status einer laufenden Aufgabe anhand ihrer ID abzurufen.
- text_to_speech: Dieses Tool wandelt den bereitgestellten Text in Sprache um.
- generate_video: Dieses Tool generiert ein Video aus einem gegebenen Prompt.
Nachdem wir nun die Tools kennen, die wir bauen werden, beginnen wir mit der Erstellung unseres Servers. Erstellen Sie zunächst eine Datei namens server.py und fügen Sie den folgenden Code hinzu:
import os
import sys
from mcp.server.fastmcp import FastMCP
import requests
import uvicorn
from starlette.applications import Starlette
from starlette.routing import Mount
base_url = "https://api.novita.ai/v3"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['NOVITA_API_KEY']}"
}
mcp = FastMCP("Novita_API")
Damit haben wir die erforderlichen Module importiert, unsere Basis-URL und Header für die API definiert und eine Instanz der FastMCP-Klasse erstellt. Fahren wir mit der Erstellung unserer Tools fort.
Modelle auflisten
Um ein Tool in FastMCP zu erstellen, müssen wir eine Funktion mit der Tool-Methode der FastMCP-Instanz dekorieren. Die Funktion list_models führt einen Aufruf an den Endpoint zum Auflisten von Modellen durch, um die Liste der Modelle abzurufen. Die Antwort wird dann entsprechend formatiert, sodass sie an das aufrufende LLM übergeben werden kann.
@mcp.tool()
def list_models() -> str:
"""
List all available models from the Novita API.
"""
url = base_url + "/openai/models"
response = requests.request("GET", url, headers=headers)
data = response.json()["data"]
text = ""
for i, model in enumerate(data, start=1):
text += f"Model id: {model['id']}\
"
text += f"Model description: {model['description']}\
"
text += f"Model type: {model['model_type']}\
\
"
return text
Der Docstring im Tool dient dazu, die Funktionalität des Tools zu beschreiben, damit das LLM versteht, wofür das Tool verwendet wird.
Modell abrufen
Dieses Tool wird verwendet, um auf die bereitgestellten LLMs auf Novita zuzugreifen. Es nimmt die Modell-ID und den Prompt für das Modell entgegen. Es verwendet den Novita Chat-Completions-API-Endpoint.
@mcp.tool()
def get_model(model_id: str, message):
"""
Provide a model ID and a message to get a response from the Novita API.
"""
url = base_url + "/openai/chat/completions"
payload = {
"model": model_id,
"messages": [
{
"content": message,
"role": "user",
}
],
"max_tokens": 200,
"response_format": {
"type": "text",
},
}
response = requests.request("POST", url, json=payload, headers=headers)
content = response.json()["choices"][0]["message"]["content"]
return content
Text2Image
Dieses Tool generiert Bilder aus einem Prompt. Es verwendet unter der Haube den Novita-Text-to-Image-Endpoint. Dieser Endpoint ist asynchron, gibt also nicht sofort das Bild zurück, sondern eine Aufgaben-ID.
@mcp.tool()
def text2Image(prompt):
"""
Generate an image from a text prompt using the Novita API.
"""
url = base_url + "/async/txt2img"
payload = {
"request": {
"model_name": "sd_xl_base_1.0.safetensors",
"prompt": prompt,
"width": 1024,
"height": 1024,
"image_num": 1,
"steps": 20,
"clip_skip": 1,
"sampler_name": "Euler a",
"guidance_scale": 7.5,
},
"extra": {
"response_image_type": "jpeg"
}
}
response = requests.request("POST", url, json=payload, headers=headers)
return response.json()["task_id"]
Aufgabenergebnis
Dieses Tool wird verwendet, um den Status einer laufenden Aufgabe auf der Novita-API abzurufen. Es nimmt nur die Aufgaben-ID entgegen. Beispielsweise generiert das Image-Tool asynchron ein Bild und gibt eine Aufgaben-ID an den Host zurück. Der Benutzer kann dann den Host bitten, das Ergebnis dieser Aufgabe mit dem Task-Result-Tool abzurufen.
@mcp.tool()
def task_result(task_id: str):
"""
Get the current status of a running task using it's task id
"""
url = base_url + f'/async/task-result?task_id={task_id}'
response = requests.request("GET", url, headers=headers)
return response.json()
Video generieren
Dieses Tool generiert Videos mit dem Kling AI V1.6 Text-to-Video-Endpoint der Novita-API. Genau wie das Image-Tool generiert es Videos asynchron und gibt eine Aufgaben-ID zurück.
@mcp.tool()
def generateVideo(prompt: str):
"""
Generate an image using a prompt
"""
url = base_url + "/async/kling-v1.6-t2v"
payload = {
"mode": "Standard",
"prompt": prompt,
"negative_prompt": "low quality",
"guidance_scale": 0.6
}
response = requests.post(url, json=payload, headers=headers)
return response.json()
Text To Speech
Dieses Tool generiert Sprache mit dem Novita-Text-to-Speech-Endpoint. Es ist ebenfalls ein asynchroner Endpoint und gibt ebenfalls eine Aufgaben-ID zurück.
@mcp.tool()
def textToSpeech(text, voice_id) -> str:
"""
Generate speech using text and voice id.
It returns the task id of the generated speech.
The available voice ids are:
- Emily
- James
- Olivia
- Michael
- Sarah
- John
"""
url = base_url + "/async/txt2speech"
payload = {
"request": {
"voice_id": voice_id,
"language": "en-US",
"texts": [text]
}
}
response = requests.post(url, json=payload, headers=headers)
return response.json()["task_id"]
Nachdem alle Tools definiert sind, können wir unseren Transportmechanismus einrichten. Wir werden stdio verwenden.
if __name__ == "__main__":
# Run using stdio transport
mcp.run(transport="stdio")
Jetzt können wir den gesamten Code zusammenführen:
import os
import sys
from mcp.server.fastmcp import FastMCP
import requests
import uvicorn
from starlette.applications import Starlette
from starlette.routing import Mount
base_url = "https://api.novita.ai/v3"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['NOVITA_API_KEY']}"
}
mcp = FastMCP("Novita_API")
@mcp.tool()
def list_models() -> str:
"""
List all available models from the Novita API.
"""
url = base_url + "/openai/models"
response = requests.request("GET", url, headers=headers)
data = response.json()["data"]
text = ""
for i, model in enumerate(data, start=1):
text += f"Model id: {model['id']}\
"
text += f"Model description: {model['description']}\
"
text += f"Model type: {model['model_type']}\
\
"
return text
@mcp.tool()
def get_model(model_id: str, message) -> str:
"""
Provide a model ID and a message to get a response from the Novita API.
"""
url = base_url + "/openai/chat/completions"
payload = {
"model": model_id,
"messages": [
{
"content": message,
"role": "user",
}
],
"max_tokens": 200,
"response_format": {
"type": "text",
},
}
response = requests.request("POST", url, json=payload, headers=headers)
content = response.json()["choices"][0]["message"]["content"]
return content
@mcp.tool()
def text2Image(prompt: str) -> str:
"""
Generate an image from a text prompt using the Novita API.
"""
url = base_url + "/async/txt2img"
payload = {
"request": {
"model_name": "sd_xl_base_1.0.safetensors",
"prompt": prompt,
"width": 1024,
"height": 1024,
"image_num": 1,
"steps": 20,
"clip_skip": 1,
"sampler_name": "Euler a",
"guidance_scale": 7.5,
},
"extra": {
"response_image_type": "jpeg"
}
}
response = requests.request("POST", url, json=payload, headers=headers)
return response.json()["task_id"]
@mcp.tool()
def task_result(task_id: str) -> str:
"""
Get the current status of a running task using it's task id
"""
url = base_url + f'/async/task-result?task_id={task_id}'
response = requests.request("GET", url, headers=headers)
return response.json()
@mcp.tool()
def generateVideo(prompt: str) -> str:
"""
Generate an image using a prompt
"""
url = base_url + "/async/kling-v1.6-t2v"
payload = {
"mode": "Standard",
"prompt": prompt,
"negative_prompt": "low quality",
"guidance_scale": 0.6
}
response = requests.post(url, json=payload, headers=headers)
return response.json()["task_id"]
@mcp.tool()
def textToSpeech(text, voice_id) -> str:
"""
Generate speech using text and voice id.
It returns the task id of the generated speech.
The available voice ids are:
- Emily
- James
- Olivia
- Michael
- Sarah
- John
"""
url = base_url + "/async/txt2speech"
payload = {
"request": {
"voice_id": voice_id,
"language": "en-US",
"texts": [text]
}
}
response = requests.post(url, json=payload, headers=headers)
return response.json()["task_id"]
if __name__ == "__main__":
# Run using stdio transport
mcp.run(transport="stdio")
Wir können unseren MCP-Server auf jedem MCP-Host testen, wie Claude Desktop, Cursor oder VS Code, mit folgender Konfiguration:
{
"command": "python",
"args": [
"path/to/server.py"
],
"env": {
"NOVITA_API_KEY": "sk_...."
}
}
Wir können auch das zuvor entwickelte Client-Skript verwenden, um unseren Server zu testen.
Verwendung des MCP Low-Level-Servers
Der Server, den wir im vorherigen Abschnitt erstellt haben, verwendet die FastMCP-Klasse, die eine High-Level-Schnittstelle zum Erstellen von MCP-Servern bietet. Sie können MCP-Server auch mit dem Low-Level-Server erstellen, der eine detaillierte Kontrolle über das MCP-Protokoll ermöglicht. Sehen wir uns an, wie wir den Server aus dem vorherigen Abschnitt anpassen können, um den Low-Level-Server zu verwenden.
Tool-Verwaltung
Eine der Aufgaben von FastMCP ist die Verwaltung der von Ihnen definierten Tools. Wenn Sie eine Funktion mit dem Tool-Dekorator der FastMCP-Klasse dekorieren, fügt FastMCP dieses Tool zu einer Liste hinzu. Wenn der Agent dieses Tool anfordert, ruft FastMCP es ab, führt es aus und sendet das Ergebnis dann an den Agenten zurück.
Mit dem Low-Level-Server können wir diesen Prozess selbst verwalten, indem wir den call_tool-Dekorator verwenden.
@app.call_tool()
async def manage_tool(name: str, arguments: dict ) -> list[types.TextContent]:
if name == "list_models":
return await list_models_tool()
if name == "get_model":
return await get_model_tool(arguments)
else:
raise ValueError(f"Unknown tool: {name}")
Der obige Code zeigt eine Funktion, die mit der call_tool-Methode dekoriert wurde. Wenn der Agent ein Tool aufruft, übergibt er den Namen des Tools und alle Argumente, die das Tool erwartet. Anhand des Funktionsnamens können wir dann bestimmen, welches Tool der Agent aufrufen möchte, und es ausführen.
Wir können auch die Auflistung der Tools mit dem Low-Level-Server selbst verwalten, anders als bei FastMCP, das dies automatisch erledigt, wenn eine Funktion mit der Tool-Methode dekoriert wurde.
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="list_models",
description="List all available models from the Novita API.",
inputSchema={"type": "object", "properties": {}},
),
types.Tool(
name="get_model",
description="Provide a model ID and a message to get a response from the Novita API.",
inputSchema={
"type": "object",
"required": ["model_id", "message"],
"properties": {
"model_id": {
"type": "string",
"description": "The ID of the model to use.",
},
"message": {
"type": "string",
"description": "The input message to send.",
},
},
},
),
]
Hier ist der vollständige Code des Low-Level-Servers. Er enthält zwei Tools und kann über Standardeingabe und -ausgabe mit dem Client kommunizieren.
import os
import asyncio
import requests
from mcp.server.lowlevel import Server
from mcp.server.stdio import stdio_server
import mcp.types as types
base_url = "https://api.novita.ai/v3"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['NOVITA_API_KEY']}"
}
app = Server("Novita_API")
async def list_models_tool():
"""
Lists all available models from the Novita API.
"""
url = base_url + "/openai/models"
response = requests.get(url, headers=headers)
data = response.json()["data"]
text = ""
for i, model in enumerate(data, start=1):
text += f"Model id: {model['id']}\
"
text += f"Model description: {model['description']}\
"
text += f"Model type: {model['model_type']}\
\
"
return [types.TextContent(type="text", text=text)]
async def get_model_tool(arguments: dict):
"""
Given a model ID and a user message, fetch a response from the Novita API.
"""
model_id = arguments.get("model_id")
message = arguments.get("message")
if not model_id or not message:
raise ValueError("Both 'model_id' and 'message' are required.")
url = base_url + "/openai/chat/completions"
payload = {
"model": model_id,
"messages": [
{
"content": message,
"role": "user",
}
],
"max_tokens": 200,
"response_format": {
"type": "text",
},
}
response = requests.post(url, json=payload, headers=headers)
content = response.json()["choices"][0]["message"]["content"]
return [types.TextContent(type="text", text=content)]
@app.call_tool()
async def manage_tool(name: str, arguments: dict ) -> list[types.TextContent]:
if name == "list_models":
return await list_models_tool()
if name == "get_model":
return await get_model_tool(arguments)
else:
raise ValueError(f"Unknown tool: {name}")
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="list_models",
description="List all available models from the Novita API.",
inputSchema={"type": "object", "properties": {}},
),
types.Tool(
name="get_model",
description="Provide a model ID and a message to get a response from the Novita API.",
inputSchema={
"type": "object",
"required": ["model_id", "message"],
"properties": {
"model_id": {
"type": "string",
"description": "The ID of the model to use.",
},
"message": {
"type": "string",
"description": "The input message to send.",
},
},
},
),
]
async def main():
async with stdio_server() as streams:
await app.run(streams[0], streams[1], app.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())
Der Low-Level-Server bietet nicht nur eine feingranulare Kontrolle über die Tool-Verwaltung, sondern auch eine Low-Level-Steuerung über Ressourcen, Prompts und andere Teile des MCP-Protokolls, wie z. B. das Lebenszyklusmanagement.
Fazit
In diesem Tutorial haben wir einen MCP-Server erstellt, der die Novita-API nutzt, um die Fähigkeiten jedes MCP-Hosts zu erweitern. Sie haben die Grundlagen kennengelernt, die für die Erstellung eines MCP-Servers erforderlich sind, einschließlich der Definition und Bereitstellung von Tools.
Mit diesem Fundament können Sie beginnen, fortgeschrittenere Themen zu erkunden, wie Authentifizierung, die Bereitstellung entfernter MCP-Server und die direkte Arbeit mit der Low-Level-Python-Implementierung.
Wir haben auch die Novita-API selbst erkundet und ihre Fähigkeiten gesehen, von einer vielfältigen Sammlung von Sprachmodellen bis hin zu Generierungstools für Video, Audio und Bilder. Besuchen Sie den Novita LLM Playground, um auch andere APIs auszuprobieren, die wir nicht behandelt haben, wie die Endpoints für Bild- und Gesichtsbearbeitung.
Novita AI ist eine KI-Cloud-Plattform, die Entwicklern eine einfache Möglichkeit bietet, KI-Modelle mit unserer einfachen API bereitzustellen, und gleichzeitig eine erschwingliche und zuverlässige GPU-Cloud zum Aufbau und zur Skalierung bereitstellt.
