Skip to main content
Glama

Myrcael

by noname9091

ソヴァ

クライアント セッションを処理できるMCPサーバーを構築するための TypeScript フレームワーク。

[!注記]

Python 実装については、 sovaを参照してください。

特徴

インストール

npm install sova

クイックスタート

[!注記]

sova の実際の使用例は数多くあります。例についてはショーケースをご覧ください。

import { sova } from "sova"; import { z } from "zod"; // Or any validation library that supports Standard Schema const server = new sova({ 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", });

これで完了です。MCPサーバーが稼働しました。

ターミナルでサーバーをテストするには、次のコマンドを使用します。

git clone https://github.com/bounded1999/sova.git cd sova 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

南南東

Server-Sent Events (SSE) は、サーバーがHTTPS接続を介してクライアントにリアルタイム更新を送信するためのメカニズムを提供します。MCPのコンテキストでは、SSEは主にリモートMCP通信を可能にするために使用され、リモートマシンにホストされているMCPにアクセスし、ネットワーク経由で更新を中継することを可能にします。

SSE サポートを使用してサーバーを実行することもできます。

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

これにより、サーバーが起動し、 http://localhost:8080/sseで SSE 接続をリッスンします。

次に、 SSEClientTransportを使用してサーバーに接続します。

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);

コアコンセプト

ツール

MCP のツールを使用すると、サーバーは、クライアントが呼び出して LLM がアクションを実行するために使用できる実行可能関数を公開できます。

sova はツールパラメータの定義に標準スキーマ仕様を使用します。これにより、仕様を実装している限り、お好みのスキーマ検証ライブラリ(Zod、ArkType、Valibot など)を使用できます。

ゾッドの例:

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の例:

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の例:

Valibot にはピア依存関係 @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); }, });
文字列を返す

execute文字列を返すことができます:

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

後者は以下と同等です:

server.addTool({ name: "download", description: "Download a file", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "text", text: "Hello, world!", }, ], }; }, });
リストを返す

メッセージのリストを返す場合は、 contentプロパティを持つオブジェクトを返すことができます。

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" }, ], }; }, });
画像を返す

画像のコンテンツ オブジェクトを作成するには、 imageContentを使用します。

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(...) // ], // }; }, });

imageContent関数は次のオプションを受け取ります。

  • url : 画像の URL。
  • path : 画像ファイルへのパス。
  • buffer : バッファとしてのイメージデータ。

urlpathbufferのいずれか 1 つだけを指定する必要があります。

上記の例は次の例と同等です。

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", }, ], }; }, });
オーディオを返す

audioContentを使用してオーディオのコンテンツ オブジェクトを作成します。

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(...) // ], // }; }, });

audioContent関数は次のオプションを受け取ります。

  • url : オーディオの URL。
  • path : オーディオファイルへのパス。
  • buffer : バッファとしてのオーディオデータ。

urlpathbufferのいずれか 1 つだけを指定する必要があります。

上記の例は次の例と同等です。

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", }, ], }; }, });
組み合わせ型を返す

このように様々なタイプを組み合わせてAIに送り返すことができます

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, // ], // }; // }, });
ログ記録

ツールは、コンテキスト オブジェクト内のlogオブジェクトを使用してクライアントにメッセージを記録できます。

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"; }, });

logオブジェクトには次のメソッドがあります。

  • debug(message: string, data?: SerializableValue)
  • error(message: string, data?: SerializableValue)
  • info(message: string, data?: SerializableValue)
  • warn(message: string, data?: SerializableValue)
エラー

ユーザーに表示されるエラーは、 UserErrorインスタンスとしてスローされる必要があります。

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"; }, });
進捗

ツールは、コンテキスト オブジェクトでreportProgressを呼び出すことによって進行状況を報告できます。

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"; }, });
ツール注釈

MCP 仕様 (2025-03-26) の時点では、ツールの動作に関するメタデータを追加することで、より豊富なコンテキストと制御を提供する注釈をツールに含めることができます。

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); }, });

利用可能な注釈は次のとおりです。

注釈タイプデフォルト説明
title-ツールの人間が読めるタイトル。UI 表示に役立ちます。
readOnlyHintブール値falsetrueの場合、ツールは環境を変更しないことを示します。
destructiveHintブール値truetrue の場合、ツールは破壊的な更新を実行する可能性があります ( readOnlyHintが false の場合にのみ意味があります)
idempotentHintブール値falsetrue の場合、同じ引数でツールを繰り返し呼び出しても追加の効果はありません ( readOnlyHintが false の場合にのみ意味があります)
openWorldHintブール値true真の場合、ツールは外部エンティティの「オープンワールド」と対話する可能性があります

これらの注釈は、クライアントと LLM がツールの使用方法や、ツールを呼び出すときに何を期待できるかをよりよく理解するのに役立ちます。

リソース

リソースとは、MCPサーバーがクライアントに提供したいあらゆる種類のデータを指します。これには以下が含まれます。

  • ファイルの内容
  • スクリーンショットと画像
  • その他

各リソースは一意の URI によって識別され、テキストまたはバイナリ データのいずれかを含めることができます。

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

[!注記]

load複数のリソースを返すことができます。例えば、ディレクトリを読み込んだ際に、そのディレクトリ内のファイルのリストを返すなど、様々な用途に利用できます。

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

loadでバイナリコンテンツを返すこともできます。

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

リソーステンプレート

リソース テンプレートを定義することもできます。

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}`, }; }, });
リソーステンプレート引数の自動補完

自動補完を有効にするには、リソース テンプレート引数にcomplete関数を提供します。

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}`, }; }, });

プロンプト

プロンプトを使用すると、サーバーは再利用可能なプロンプトテンプレートとワークフローを定義でき、クライアントはそれらをユーザーやLLMに簡単に表示できます。これにより、LLMの一般的なインタラクションを標準化し、共有するための強力な手段となります。

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}`; }, });
プロンプト引数の自動補完

プロンプトでは引数の自動補完が可能です。

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: [], }; }, }, ], });
enumを使用したプロンプト引数の自動補完

引数にenum配列を指定すると、サーバーは自動的に引数の補完を提供します。

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"], }, ], });

認証

sova を使用すると、カスタム関数を使用してクライアントauthenticateできます。

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, }; }, });

これで、ツールで認証されたセッション データにアクセスできるようになります。

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

指示の提供

instructionsオプションを使用してサーバーに指示を与えることができます。

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.', });

セッション

sessionオブジェクトはsovaSessionのインスタンスであり、アクティブなクライアント セッションを記述します。

server.sessions;

クライアントとサーバー間の 1:1 通信を可能にするために、クライアント接続ごとに新しいサーバー インスタンスを割り当てます。

型付きサーバーイベント

onメソッドを使用して、サーバーによって発行されたイベントをリッスンできます。

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

sovaSession

sovaSessionクライアント セッションを表し、クライアントと対話するためのメソッドを提供します。

sovaSessionインスタンスを取得する方法の例については、 「セッション」を参照してください。

requestSampling

requestSamplingサンプリング要求を作成し、応答を返します。

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

clientCapabilitiesプロパティにはクライアント機能が含まれます。

session.clientCapabilities;

loggingLevel

loggingLevelプロパティは、クライアントによって設定されたログ記録レベルを表します。

session.loggingLevel;

roots

rootsプロパティには、クライアントによって設定されたルートが含まれます。

session.roots;

server

serverプロパティには、セッションに関連付けられた MCP サーバーのインスタンスが含まれます。

session.server;

型付けされたセッションイベント

onメソッドを使用して、セッションによって発行されたイベントをリッスンできます。

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

サーバーの実行

mcp-cliでテストする

サーバーをテストおよびデバッグする最も速い方法はsova devを使用することです。

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

これにより、ターミナルで MCP サーバーをテストおよびデバッグするために、 mcp-cliを使用してサーバーが実行されます。

MCP Inspectorで検査する

もう 1 つの方法は、公式のMCP Inspector使用して Web UI でサーバーを検査することです。

npx sova inspect server.ts

よくある質問

Claude Desktop ではどのように使用しますか?

ガイドhttps://modelcontextprotocol.io/quickstart/userに従って、次の構成を追加します。

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

謝辞

-
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.

クラ��アント セッション、認証、画像/オーディオ コンテンツ、型付けされたサーバー イベントの機能を備えた MCP サーバーを構築するための TypeScript フレームワーク。

  1. 特徴
    1. インストール
      1. クイックスタート
        1. 南南東
      2. コアコンセプト
        1. ツール
        2. リソース
        3. リソーステンプレート
        4. プロンプト
        5. 認証
        6. 指示の提供
        7. セッション
        8. 型付きサーバーイベント
      3. sovaSession
        1. requestSampling
        2. clientCapabilities
        3. loggingLevel
        4. roots
        5. server
        6. 型付けされたセッションイベント
      4. サーバーの実行
        1. mcp-cliでテストする
        2. MCP Inspectorで検査する
      5. よくある質問
        1. Claude Desktop ではどのように使用しますか?
      6. 謝辞

        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