easy-mcp について
easy-mcp は、プロトコルの仕組みや定型コードを隠す簡潔な宣言で MCP サーバーを作成する TypeScript フレームワークです。MCP サーバーを素早く構築したい開発者向けで、引数の型を推論する実験的なデコレーター API を備えています。現在はベータ版です。
主な機能
- 01Express に似た簡潔な API
- 02引数を推論する実験的なデコレーター API
- 03ログ出力と進捗報告のコンテキストオブジェクト
- 04TypeScript による型安全性
活用シーン
- 01ツールとリソースを備えた MCP サーバーの迅速な構築
- 02入力スキーマを手書きせずにツールを定義
- 03MCP サーバーのリソーステンプレートとルートの宣言
MCP 対応
easy-mcp は MCP サーバーを作成するためのフレームワークで、ツール、プロンプト、リソース、リソーステンプレート、ルートを定義して MCP クライアントに公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
easy-mcp

EasyMCP は利用できますが、ベータ版です。問題が発生した場合はご報告ください。
EasyMCP は、TypeScript で Model Context Protocol(MCP)サーバーを作成する最も簡単な方法です。
配線、フォーマット、その他の定型的な定義を、シンプルな宣言の背後に隠します。
EasyMCP では、使い始めるために必要な最小限の定義だけを記述できます。また、より複雑なリソース、テンプレート、ツール、プロンプトを定義することもできます。
特長
- Express のようにシンプルな API:EasyMCP は、高水準で直感的な API を提供します。ExpressJS でエンドポイントを定義するのと同様の呼び出しで、ツール、プロンプト、リソース、リソーステンプレート、ルートを定義できます。省略可能なパラメーターはすべて省略でき、必要になるまで表示されません。
- 実験的なデコレーター API:ツール、プロンプト、リソースの引数を自動的に推論します。入力スキーマの定義は不要です。
- コンテキストオブジェクト:ツール内でコンテキストオブジェクトを通じて、ログ記録や進捗報告などの MCP 機能にアクセスできます。
- 優れた型安全性:開発者体験が向上し、実行時エラーが減少します。
ベータ版の制限事項
- MCP サンプリングにはまだ対応していません
- SSE にはまだ対応していません
- リソース更新通知にはまだ対応していません
- プロンプトは技術的には入力を受け付けますが、Typescript SDK では入力を受け付けないとされています。そのため、この機能は未完成に感じられます。
インストール
EasyMCP をインストールするには、プロジェクトディレクトリで次のコマンドを実行します。
bun install
(実験的)デコレーター API を使ったクイックスタート
examples/express-decorators.ts も参照するか、bun start:decorators を実行してください。
EasyMCP のデコレーター API は非常にシンプルで、型と入力設定を自動的に推論します。
ただし、実験的な機能であり、変更されたり、まだ発見されていない問題があったりする可能性があります。
import EasyMCP from "./lib/EasyMCP";
import { Tool, Resource, Prompt } from "./lib/experimental/decorators";
class MyMCP extends EasyMCP {
@Resource("greeting/{name}")
getGreeting(name: string) {
return `Hello, ${name}!`;
}
@Prompt()
greetingPrompt(name: string) {
return `Generate a greeting for ${name}.`;
}
@Tool()
greet(name: string, optionalContextFromServer: Context) {
optionalContextFromServer.info(`Greeting ${name}`);
return `Hello, ${name}!`;
}
}
const mcp = new MyMCP({ version: "1.0.0" });
デコレーター API を使った複雑な例
examples/express-express.ts を参照するか、bun start:express を実行してください。
import EasyMCP from "./lib/EasyMCP";
import { Prompt } from "./lib/decorators/Prompt";
import { Resource } from "./lib/decorators/Resource";
import { Root } from "./lib/decorators/Root";
import { Tool } from "./lib/decorators/Tool";
@Root("/my-sample-dir/photos")
@Root("/my-root-dir", { name: "My laptop's root directory" }) // Optionally you can name the root
class ZachsMCP extends EasyMCP {
/**
You can declare a Tool with zero configuration. Relevant types and plumbing will be inferred and handled.
By default, the name of the Tool will be the name of the method.
*/
@Tool()
simpleFunc(nickname: string, height: number) {
return `${nickname} of ${height} height`;
}
/**
* You can enhance a tool with optional data like a description.
Due to limitations in Typescript, if you want the Tool to serialize certain inputs as optional to the Client, you need to provide an optionals list.
*/
@Tool({
description: "An optional description",
optionals: ["active", "items", "age"],
})
middleFunc(name: string, active?: string, items?: string[], age?: number) {
return `exampleFunc called: name ${name}, active ${active}, items ${items}, age ${age}`;
}
/**
* You can also provide a schema for the input arguments of a tool, if you want full control.
*/
@Tool({
description: "A function with various parameter types",
parameters: [
{
name: "date",
type: "string",
optional: false,
},
{
name: "season",
type: "string",
optional: false,
},
{
name: "year",
type: "number",
optional: true,
},
],
})
complexTool(date: string, season: string, year?: number) {
return `complexTool called: date ${date}, season ${season}, year ${year}`;
}
/**
* Tools can use a context object to access MCP capabilities like logging, progress reporting, and meta data from the request
*/
@Tool({
description: "A tool that uses context",
})
async processData(dataSource: string, context: Context) {
context.info(`Starting to process data from ${dataSource}`);
try {
const data = await context.readResource(dataSource);
context.debug("Data loaded");
for (let i = 0; i < 5; i++) {
await new Promise((resolve) => setTimeout(resolve, 1000));
await context.reportProgress(i * 20, 100);
context.info(`Processing step ${i + 1} complete`);
}
return `Processed ${data.length} bytes of data from ${dataSource}`;
} catch (error) {
context.error(`Error processing data: ${(error as Error).message}`);
throw error;
}
}
/**
* Resources can be declared with a simple URI.
By default, the name of the resource will be the name of the method.
*/
@Resource("simple-resource")
simpleResource() {
return "Hello, world!";
}
/**
* Or include handlebars which EasyMCP will treat as a Resource Template.
Both Resources and Resource Templates can be configured with optional data like a description.
*/
@Resource("greeting/{name}")
myResourceTemplate(name: string) {
return `Hello, ${name}!`;
}
/**
* By default, prompts need no configuration.
They will be named after the method they decorate.
*/
@Prompt()
simplePrompt(name: string) {
return `Prompting... ${name}`;
}
/**
* Or you can override and configure a Prompt with a name, description, and explicit arguments.
*/
@Prompt({
name: "configured-prompt",
description: "A prompt with a name and description",
args: [
{
name: "name",
description: "The name of the thing to prompt",
required: true,
},
],
})
configuredPrompt(name: string) {
return `Prompting... ${name}`;
}
}
const mcp = new ZachsMCP({ version: "1.0.0" });
console.log(mcp.name, "is now serving!");
Express のような API を使ったクイックスタート
examples/example-minimal.ts も参照するか、bun start:express を実行してください。
この API はより詳細な記述が必要で、魔法のような動作も少ない一方、より安定しており、テストも充実しています。
import EasyMCP from "easy-mcp";
const mcp = EasyMCP.create("my-mcp-server", {
version: "0.1.0",
});
// Define a resource
mcp.resource({
uri: "dir://desktop",
name: "Desktop Directory", // Optional
description: "Lists files on the desktop", // Optional
mimeType: "text/plain", // Optional
fn: async () => {
return "file://desktop/file1.txt\nfile://desktop/file2.txt";
},
});
// Define a resource template
mcp.template({
uriTemplate: "file://{filename}",
name: "File Template", // Optional
description: "Template for accessing files", // Optional
mimeType: "text/plain", // Optional
fn: async ({ filename }) => {
return `Contents of ${filename}`;
},
});
// Define a tool
mcp.tool({
name: "greet",
description: "Greets a person", // Optional
inputs: [ // Optional
{
name: "name",
type: "string",
description: "The name to greet",
required: true,
},
],
fn: async ({ name }) => {
return `Hello, ${name}!`;
},
});
// Define a prompt
mcp.prompt({
name: "introduction",
description: "Generates an introduction", // Optional
args: [ // Optional
{
name: "name",
type: "string",
description: "Your name",
required: true,
},
],
fn: async ({ name }) => {
return `Hi there! My name is ${name}. It's nice to meet you!`;
},
});
// Start the server
mcp.serve().catch(console.error);
Express のような API
EasyMCP.create(name: string, options: ServerOptions)
新しい EasyMCP インスタンスを作成します。
name:MCP サーバーの名前です。options:バージョンなどのサーバーオプションです。
mcp.resource(config: ResourceConfig)
リソースを定義します。
mcp.template(config: ResourceTemplateConfig)
リソーステンプレートを定義します。
mcp.tool(config: ToolConfig)
ツールを定義します。
mcp.prompt(config: PromptConfig)
プロンプトを定義します。
mcp.root(config: Root)
ルートを定義します。
mcp.serve()
MCP サーバーを起動します。
(実験的)デコレーター API
EasyMCP では、MCP サーバーのコンポーネントをより簡潔かつ宣言的に定義するためのデコレーターを提供しています。利用可能なデコレーターの概要を以下に示します。
@Tool(config?: ToolConfig)
メソッドをツールとして定義します。メソッドに宣言した引数を受け取り、TS の型注釈に基づいて型と入力設定を推論します。MCP 機能にアクセスするため、最後の引数として省略可能な context 引数を追加できます。
config:ツールの省略可能な設定オブジェクトです。description:ツールの省略可能な説明です。optionals:省略可能として指定するパラメーター名の省略可能な配列です。parameters:入力スキーマを完全に制御するための、パラメーター定義の省略可能な配列です。
例:
@Tool({
description: "Greets a person",
optionals: ["title"],
})
greet(name: string, title?: string, optionalContext: Context) {
return `Hello, ${title ? title + " " : ""}${name}!`;
}
@Resource(uri: string, config?: Partial<ResourceDefinition>)
メソッドをリソースまたはリソーステンプレートとして定義します。リソーステンプレートは、URI で Handlebars を使用して定義します。
uri:リソースの URI または URI テンプレートです。config:リソースの省略可能な設定オブジェクトです。name:リソースの省略可能な名前です。description:リソースの省略可能な説明です。mimeType:リソースの省略可能な MIME タイプです。
例:
@Resource("greeting/{name}")
getGreeting(name: string) {
return `Hello, ${name}!`;
}
@Prompt(config?: PromptDefinition)
メソッドをプロンプトとして定義します。
config:プロンプトの省略可能な設定オブジェクトです。name:プロンプトの省略可能な名前です(デフォルトはメソッド名です)。description:プロンプトの省略可能な説明です。args:引数定義の省略可能な配列です。
例:
@Prompt({
description: "Generates a greeting prompt",
args: [
{ name: "name", description: "Name to greet", required: true },
],
})
greetingPrompt(name: string) {
return `Generate a friendly greeting for ${name}.`;
}
@Root(uri: string, config?: { name?: string })
MCP サーバーのルートディレクトリを定義します。このデコレーターはメソッドではなく、クラスに適用します。
uri:ルートディレクトリの URI です。config:省略可能な設定オブジェクトです。name:ルートの省略可能な名前です。
例:
@Root("/my-sample-dir/photos")
@Root("/my-root-dir", { name: "My laptop's root directory" })
class MyMCP extends EasyMCP {
// ...
}
デコレーターを使用すると、EasyMCP がツール、リソース、プロンプト、ルートの型を自動的に推論し、適切な設定を作成します。これにより、ボイラープレートコードを大幅に削減し、MCP サーバーの定義をより簡潔にできます。
ただし、デコレーター API は実験的なものであり、バグや予期しない変更が発生する可能性があります。
貢献
貢献を歓迎します!PR を送信してください。
ライセンス
このプロジェクトは MIT ライセンスの下でライセンスされています。
クレジット
EasyMCP は Zach Caceres によって作成されましたが、Python MCP サーバー用ライブラリである FastMCP by kjlowin に着想を得ています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。