Skip to main content
Glama

Myrcael

by noname9091

Einfach MCP

Ein TypeScript-Framework zum Erstellen von MCP -Servern, die Clientsitzungen verarbeiten können.

[!NOTIZ]

Eine Python-Implementierung finden Sie unter sova .

Merkmale

Installation

npm install sova

Schnellstart

[!NOTIZ]

Es gibt viele Beispiele für den Einsatz von Sova in der Praxis. Beispiele finden Sie im Showcase .

import { sova } from "simply"; import { z } from "zod"; // Or any validation library that supports Standard Schema const server = new simply({ name: "My Server", version: "1.0.0", }); server.addTool({ name: "add", description: "Add two numbers", parameters: z.object({ a: z.number(), b: z.number(), }), execute: async (args) => { return String(args.a + args.b); }, }); server.start({ transportType: "stdio", });

Das war's! Sie haben einen funktionierenden MCP-Server.

Sie können den Server im Terminal mit folgendem testen:

git clone https://github.com/nonameguy9091/simply.git cd simply pnpm install pnpm build # Test the addition server example using CLI: npx sova dev src/examples/addition.ts # Test the addition server example using MCP Inspector: npx sova inspect src/examples/addition.ts

SSE

Server-Sent Events (SSE) bieten Servern einen Mechanismus, um Echtzeit-Updates über eine HTTPS-Verbindung an Clients zu senden. Im Kontext von MCP wird SSE hauptsächlich verwendet, um die Remote-MCP-Kommunikation zu ermöglichen. Dadurch kann auf ein auf einem Remote-Rechner gehostetes MCP zugegriffen werden und Updates über das Netzwerk weitergeleitet werden.

Sie können den Server auch mit SSE-Unterstützung betreiben:

server.start({ transportType: "sse", sse: { endpoint: "/sse", port: 8080, }, });

Dadurch wird der Server gestartet und wartet auf SSE-Verbindungen unter http://localhost:8080/sse .

Anschließend können Sie SSEClientTransport verwenden, um eine Verbindung zum Server herzustellen:

import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; const client = new Client( { name: "example-client", version: "1.0.0", }, { capabilities: {}, }, ); const transport = new SSEClientTransport(new URL(`http://localhost:8080/sse`)); await client.connect(transport);

Kernkonzepte

Werkzeuge

Tools in MCP ermöglichen es Servern, ausführbare Funktionen verfügbar zu machen, die von Clients aufgerufen und von LLMs zum Ausführen von Aktionen verwendet werden können.

Sova verwendet die Standardschemaspezifikation zur Definition von Werkzeugparametern. Dies ermöglicht Ihnen die Verwendung Ihrer bevorzugten Schemavalidierungsbibliothek (z. B. Zod, ArkType oder Valibot), sofern diese die Spezifikation implementiert.

Zod-Beispiel:

import { z } from "zod"; server.addTool({ name: "fetch-zod", description: "Fetch the content of a url (using Zod)", parameters: z.object({ url: z.string(), }), execute: async (args) => { return await fetchWebpageContent(args.url); }, });

ArkType-Beispiel:

import { type } from "arktype"; server.addTool({ name: "fetch-arktype", description: "Fetch the content of a url (using ArkType)", parameters: type({ url: "string", }), execute: async (args) => { return await fetchWebpageContent(args.url); }, });

Valibot-Beispiel:

Valibot erfordert die Peer-Abhängigkeit @valibot/to-json-schema.

import * as v from "valibot"; server.addTool({ name: "fetch-valibot", description: "Fetch the content of a url (using Valibot)", parameters: v.object({ url: v.string(), }), execute: async (args) => { return await fetchWebpageContent(args.url); }, });
Zurückgeben einer Zeichenfolge

execute kann eine Zeichenfolge zurückgeben:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return "Hello, world!"; }, });

Letzteres ist gleichbedeutend mit:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "text", text: "Hello, world!", }, ], }; }, });
Zurückgeben einer Liste

Wenn Sie eine Liste von Nachrichten zurückgeben möchten, können Sie ein Objekt mit einer content zurückgeben:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "text", text: "First message" }, { type: "text", text: "Second message" }, ], }; }, });
Zurückgeben eines Bildes

Verwenden Sie imageContent , um ein Inhaltsobjekt für ein Bild zu erstellen:

import { imageContent } from "sova"; server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return imageContent({ url: "https://example.com/image.png", }); // or... // return imageContent({ // path: "/path/to/image.png", // }); // or... // return imageContent({ // buffer: Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", "base64"), // }); // or... // return { // content: [ // await imageContent(...) // ], // }; }, });

Die Funktion imageContent akzeptiert die folgenden Optionen:

  • url : Die URL des Bildes.
  • path : Der Pfad zur Bilddatei.
  • buffer : Die Bilddaten als Puffer.

Es darf nur eine der Optionen url , path oder buffer angegeben werden.

Das obige Beispiel ist gleichbedeutend mit:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "image", data: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", mimeType: "image/png", }, ], }; }, });
Rückgabe eines Audios

Verwenden Sie audioContent , um ein Inhaltsobjekt für ein Audio zu erstellen:

import { audioContent } from "sova"; server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return audioContent({ url: "https://example.com/audio.mp3", }); // or... // return audioContent({ // path: "/path/to/audio.mp3", // }); // or... // return audioContent({ // buffer: Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", "base64"), // }); // or... // return { // content: [ // await audioContent(...) // ], // }; }, });

Die Funktion audioContent akzeptiert die folgenden Optionen:

  • url : Die URL des Audios.
  • path : Der Pfad zur Audiodatei.
  • buffer : Die Audiodaten als Puffer.

Es darf nur eine der Optionen url , path oder buffer angegeben werden.

Das obige Beispiel ist gleichbedeutend mit:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "audio", data: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", mimeType: "audio/mpeg", }, ], }; }, });
Rückgabekombinationstyp

Auf diese Weise können Sie verschiedene Typen kombinieren und an die KI zurücksenden

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "text", text: "Hello, world!", }, { type: "image", data: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", mimeType: "image/png", }, { type: "audio", data: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", mimeType: "audio/mpeg", }, ], }; }, // or... // execute: async (args) => { // const imgContent = imageContent({ // url: "https://example.com/image.png", // }); // const audContent = audioContent({ // url: "https://example.com/audio.mp3", // }); // return { // content: [ // { // type: "text", // text: "Hello, world!", // }, // imgContent, // audContent, // ], // }; // }, });
Protokollierung

Tools können mithilfe des log im Kontextobjekt Nachrichten an den Client protokollieren:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args, { log }) => { log.info("Downloading file...", { url, }); // ... log.info("Downloaded file"); return "done"; }, });

Das log verfügt über die folgenden Methoden:

  • debug(message: string, data?: SerializableValue)
  • error(message: string, data?: SerializableValue)
  • info(message: string, data?: SerializableValue)
  • warn(message: string, data?: SerializableValue)
Fehler

Die Fehler, die dem Benutzer angezeigt werden sollen, sollten als UserError -Instanzen ausgegeben werden:

import { UserError } from "sova"; server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { if (args.url.startsWith("https://example.com")) { throw new UserError("This URL is not allowed"); } return "done"; }, });
Fortschritt

Tools können den Fortschritt melden, indem sie reportProgress im Kontextobjekt aufrufen:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args, { reportProgress }) => { reportProgress({ progress: 0, total: 100, }); // ... reportProgress({ progress: 100, total: 100, }); return "done"; }, });
Werkzeuganmerkungen

Ab der MCP-Spezifikation (26.03.2025) können Tools Anmerkungen enthalten, die durch Hinzufügen von Metadaten zum Verhalten eines Tools einen umfassenderen Kontext und mehr Kontrolle bieten:

server.addTool({ name: "fetch-content", description: "Fetch content from a URL", parameters: z.object({ url: z.string(), }), annotations: { title: "Web Content Fetcher", // Human-readable title for UI display readOnlyHint: true, // Tool doesn't modify its environment openWorldHint: true, // Tool interacts with external entities }, execute: async (args) => { return await fetchWebpageContent(args.url); }, });

Die verfügbaren Anmerkungen sind:

AnmerkungTypStandardBeschreibung
titleSchnur-Ein für Menschen lesbarer Titel für das Tool, nützlich für die UI-Anzeige
readOnlyHintBoolescher WertfalseWenn „true“, bedeutet dies, dass das Tool seine Umgebung nicht ändert.
destructiveHintBoolescher WerttrueWenn „true“, kann das Tool destruktive Updates durchführen (nur sinnvoll, wenn readOnlyHint „false“ ist).
idempotentHintBoolescher WertfalseWenn „true“, hat das wiederholte Aufrufen des Tools mit denselben Argumenten keine zusätzlichen Auswirkungen (nur sinnvoll, wenn readOnlyHint “ „false“ ist).
openWorldHintBoolescher WerttrueWenn dies zutrifft, kann das Tool mit einer „offenen Welt“ externer Entitäten interagieren.

Diese Anmerkungen helfen Kunden und LLMs dabei, besser zu verstehen, wie die Tools zu verwenden sind und was sie bei deren Aufruf erwartet.

Ressourcen

Ressourcen stellen alle Arten von Daten dar, die ein MCP-Server Clients zur Verfügung stellen möchte. Dies kann Folgendes umfassen:

  • Dateiinhalt
  • Screenshots und Bilder
  • Und mehr

Jede Ressource wird durch eine eindeutige URI identifiziert und kann entweder Text oder Binärdaten enthalten.

server.addResource({ uri: "file:///logs/app.log", name: "Application Logs", mimeType: "text/plain", async load() { return { text: await readLogFile(), }; }, });

[!NOTIZ]

load kann mehrere Ressourcen zurückgeben. Dies kann beispielsweise verwendet werden, um beim Lesen eines Verzeichnisses eine Liste der Dateien innerhalb des Verzeichnisses zurückzugeben.

async load() { return [ { text: "First file content", }, { text: "Second file content", }, ]; }

Sie können in load auch binäre Inhalte zurückgeben:

async load() { return { blob: 'base64-encoded-data' }; }

Ressourcenvorlagen

Sie können auch Ressourcenvorlagen definieren:

server.addResourceTemplate({ uriTemplate: "file:///logs/{name}.log", name: "Application Logs", mimeType: "text/plain", arguments: [ { name: "name", description: "Name of the log", required: true, }, ], async load({ name }) { return { text: `Example log content for ${name}`, }; }, });
Automatische Vervollständigung von Ressourcenvorlagenargumenten

Stellen Sie complete Funktionen für Ressourcenvorlagenargumente bereit, um die automatische Vervollständigung zu ermöglichen:

server.addResourceTemplate({ uriTemplate: "file:///logs/{name}.log", name: "Application Logs", mimeType: "text/plain", arguments: [ { name: "name", description: "Name of the log", required: true, complete: async (value) => { if (value === "Example") { return { values: ["Example Log"], }; } return { values: [], }; }, }, ], async load({ name }) { return { text: `Example log content for ${name}`, }; }, });

Eingabeaufforderungen

Mithilfe von Eingabeaufforderungen können Server wiederverwendbare Eingabeaufforderungsvorlagen und Workflows definieren, die Clients Benutzern und LLMs problemlos bereitstellen können. Sie bieten eine leistungsstarke Möglichkeit, gängige LLM-Interaktionen zu standardisieren und gemeinsam zu nutzen.

server.addPrompt({ name: "git-commit", description: "Generate a Git commit message", arguments: [ { name: "changes", description: "Git diff or description of changes", required: true, }, ], load: async (args) => { return `Generate a concise but descriptive commit message for these changes:\n\n${args.changes}`; }, });
Schnelle automatische Vervollständigung von Argumenten

Eingabeaufforderungen können eine automatische Vervollständigung ihrer Argumente bereitstellen:

server.addPrompt({ name: "countryPoem", description: "Writes a poem about a country", load: async ({ name }) => { return `Hello, ${name}!`; }, arguments: [ { name: "name", description: "Name of the country", required: true, complete: async (value) => { if (value === "Germ") { return { values: ["Germany"], }; } return { values: [], }; }, }, ], });
Schnelle automatische Vervollständigung von Argumenten mithilfe von enum

Wenn Sie ein enum Array für ein Argument angeben, stellt der Server automatisch Vervollständigungen für das Argument bereit.

server.addPrompt({ name: "countryPoem", description: "Writes a poem about a country", load: async ({ name }) => { return `Hello, ${name}!`; }, arguments: [ { name: "name", description: "Name of the country", required: true, enum: ["Germany", "France", "Italy"], }, ], });

Authentifizierung

Sova ermöglicht Ihnen die authenticate von Clients mithilfe einer benutzerdefinierten Funktion:

import { AuthError } from "sova"; const server = new sova({ name: "My Server", version: "1.0.0", authenticate: ({ request }) => { const apiKey = request.headers["x-api-key"]; if (apiKey !== "123") { throw new Response(null, { status: 401, statusText: "Unauthorized", }); } // Whatever you return here will be accessible in the `context.session` object. return { id: 1, }; }, });

Jetzt können Sie in Ihren Tools auf die authentifizierten Sitzungsdaten zugreifen:

server.addTool({ name: "sayHello", execute: async (args, { session }) => { return `Hello, ${session.id}!`; }, });

Anweisungen geben

Mit der Option instructions können Sie dem Server Anweisungen geben:

const server = new sova({ name: "My Server", version: "1.0.0", instructions: 'Instructions describing how to use the server and its features.\n\nThis can be used by clients to improve the LLM\'s understanding of available tools, resources, etc. It can be thought of like a "hint" to the model. For example, this information MAY be added to the system prompt.', });

Sitzungen

Das session ist eine Instanz von sovaSession und beschreibt aktive Clientsitzungen.

server.sessions;

Wir weisen jeder Clientverbindung eine neue Serverinstanz zu, um eine 1:1-Kommunikation zwischen Client und Server zu ermöglichen.

Typisierte Serverereignisse

Sie können mit der Methode on auf vom Server ausgegebene Ereignisse warten:

server.on("connect", (event) => { console.log("Client connected:", event.session); }); server.on("disconnect", (event) => { console.log("Client disconnected:", event.session); });

sovaSession

sovaSession stellt eine Client-Sitzung dar und bietet Methoden zur Interaktion mit dem Client.

Beispiele zum Abrufen einer sovaSession Instanz finden Sie unter „Sitzungen“ .

requestSampling

requestSampling erstellt eine Sampling -Anforderung und gibt die Antwort zurück.

await session.requestSampling({ messages: [ { role: "user", content: { type: "text", text: "What files are in the current directory?", }, }, ], systemPrompt: "You are a helpful file system assistant.", includeContext: "thisServer", maxTokens: 100, });

clientCapabilities

Die Eigenschaft clientCapabilities enthält die Clientfunktionen.

session.clientCapabilities;

loggingLevel

Die Eigenschaft loggingLevel beschreibt die vom Client festgelegte Protokollierungsebene.

session.loggingLevel;

roots

Die roots -Eigenschaft enthält die vom Client festgelegten Roots.

session.roots;

server

Die server enthält eine Instanz des MCP-Servers, der mit der Sitzung verknüpft ist.

session.server;

Typisierte Sitzungsereignisse

Sie können mit der Methode on auf von der Sitzung ausgegebene Ereignisse warten:

session.on("rootsChanged", (event) => { console.log("Roots changed:", event.roots); }); session.on("error", (event) => { console.error("Error:", event.error); });

Ausführen Ihres Servers

Testen mit mcp-cli

Der schnellste Weg zum Testen und Debuggen Ihres Servers ist mit sova dev :

npx sova dev server.js npx sova dev server.ts

Dadurch wird Ihr Server mit mcp-cli ausgeführt, um Ihren MCP-Server im Terminal zu testen und zu debuggen.

Prüfen mit MCP Inspector

Eine andere Möglichkeit besteht darin, den offiziellen MCP Inspector zu verwenden, um Ihren Server mit einer Web-Benutzeroberfläche zu überprüfen:

npx sova inspect server.ts

Häufig gestellte Fragen

Wie verwende ich es mit Claude Desktop?

Folgen Sie der Anleitung https://modelcontextprotocol.io/quickstart/user und fügen Sie die folgende Konfiguration hinzu:

{ "mcpServers": { "my-mcp-server": { "command": "npx", "args": ["tsx", "/PATH/TO/YOUR_PROJECT/src/index.ts"], "env": { "YOUR_ENV_VAR": "value" } } } }

Danksagung

-
security - not tested
A
license - permissive license
-
quality - not tested

hybrid server

The server is able to function both locally and remotely, depending on the configuration or use case.

Ein TypeScript-Framework zum Erstellen von MCP-Servern mit Funktionen für Clientsitzungen, Authentifizierung, Bild-/Audioinhalte und typisierte Serverereignisse.

  1. Merkmale
    1. Installation
      1. Schnellstart
        1. SSE
      2. Kernkonzepte
        1. Werkzeuge
        2. Ressourcen
        3. Ressourcenvorlagen
        4. Eingabeaufforderungen
        5. Authentifizierung
        6. Anweisungen geben
        7. Sitzungen
        8. Typisierte Serverereignisse
      3. sovaSession
        1. requestSampling
        2. clientCapabilities
        3. loggingLevel
        4. roots
        5. server
        6. Typisierte Sitzungsereignisse
      4. Ausführen Ihres Servers
        1. Testen mit mcp-cli
        2. Prüfen mit MCP Inspector
      5. Häufig gestellte Fragen
        1. Wie verwende ich es mit Claude Desktop?
      6. Danksagung

        Related MCP Servers

        • A
          security
          A
          license
          A
          quality
          A TypeScript-based server that allows calling other MCP clients from your own MCP client, facilitating task delegation and context window offloading for enhanced multi-agent interactions.
          Last updated -
          3
          14
          JavaScript
          MIT License
          • Apple
        • A
          security
          F
          license
          A
          quality
          A TypeScript-based MCP server designed for experimentation and integration with Calude Desktop and Cursor IDE, offering a modular playground for extending server capabilities.
          Last updated -
          2
          1,133
          4
          JavaScript
        • -
          security
          F
          license
          -
          quality
          A TypeScript framework for building Model Context Protocol (MCP) servers with automatic discovery and loading of tools, resources, and prompts.
          Last updated -
          67
          TypeScript
          • Apple
        • -
          security
          F
          license
          -
          quality
          A simple TypeScript library for creating Model Context Protocol (MCP) servers with features like type safety, parameter validation, and a minimal code API.
          Last updated -
          1
          TypeScript
          MIT License

        View all related MCP servers

        MCP directory API

        We provide all the information about MCP servers via our MCP API.

        curl -X GET 'https://glama.ai/api/mcp/v1/servers/noname9091/myrcael'

        If you have feedback or need assistance with the MCP directory API, please join our Discord server