back to all blogsすべてのブログ投稿を表示

AIツールとしてLibertyのビジネスロジックを公開する - MCP機能ガイド

image of author image of author
Theo Gkoumas and Ismath Badsha (校正) 2026年8月25日
他言語版へのリンク: English ,

MCP とは何か?

Model Context Protocol (MCP) は、AI アプリケーションが外部システムと連携して活用できるようにするオープンスタンダードです。Open Liberty の mcp-1.0 の機能により、開発者はアプリケーションのビジネスロジックを公開し、AI アプリケーションから検出、理解、呼び出しが可能になります。

MCP の強み

MCP は、AI アプリケーションが外部ソースからリアルタイム情報にアクセスするための標準として台頭してきました。このアプローチにより、AI モデルを新しい情報で常に再学習させる必要なく、より正確でタイムリーな応答が実現します。

例えば、複数のデータソースから継続的に更新が必要な気象予報サービスを提供するシナリオを考えてみましょう。ライブデータや頻繁に変化するデータをモデルの学習に直接含めることはできません。そこで、AI が*ツール*(AI が必要な時にいつでも呼び出せる関数)を通じて直接このライブデータを取得できるようにします。

これこそが Liberty の mcp-1.0 の機能が実現することです。既存の Java アプリケーションには、AI エージェントが必要とするビジネスロジック(データの取得、計算の実行、データベースへの書き込み、外部サービスの呼び出しなど)がすでに含まれています。mcp-1.0 を使えば、いくつかのアノテーションを追加するだけで、そのロジックを MCP 対応の AI エージェントに公開できます。

次のような通常の Java メソッドは:

public String getForecast(String latitude, String longitude) {
    return weatherClient.getForecast(latitude, longitude);
}

@Tool と @ToolArg を追加することで、AI から呼び出し可能なツールになります:

@Tool(name = "getForecast",
      description = "Get the current weather forecast for a location.")
public String getForecast(
        @ToolArg(name = "latitude",  description = "Latitude of the location")  String latitude,
        @ToolArg(name = "longitude", description = "Longitude of the location") String longitude) {
    return weatherClient.getForecast(latitude, longitude);
}

AI エージェントはこれらの説明を読んで、ツールが何をするのか、どのような値を指定すればよいかを理解します。

はじめに

MCP API 依存関係の追加

mcp-1.0 の機能は mcp-java API(org.mcpjava:mcp-server-api)を使用しており、Maven Central から利用できます。

pom.xml ファイルに以下の依存関係を追加してください:

<!-- MCP Server API -->
<dependency>
    <groupId>org.mcpjava</groupId>
    <artifactId>mcp-server-api</artifactId>
    <version>1.0.0</version>
    <scope>provided</scope>
</dependency>

@Schema、DefaultValueConverter、ToolManager、ToolResponseEncoder などの一部の機能は Liberty MCP API によって提供されており、Maven Central から利用できます。pom.xml ファイルに provided スコープの依存関係として追加してください:

<!-- Liberty MCP API -->
<dependency>
    <groupId>io.openliberty.api</groupId>
    <artifactId>io.openliberty.mcp</artifactId>
    <version>1.0.117</version>
    <scope>provided</scope>
</dependency>

機能の有効化

server.xml ファイルに mcp-1.0 を追加してください:

<featureManager>
    <feature>servlet-6.0</feature>
    <feature>cdi-4.0</feature>
    <feature>mcp-1.0</feature>
</featureManager>

MCP エンドポイント URL の確認

アプリケーションをデプロイすると、mcp-1.0 の機能が Liberty のメッセージ・ログに完全な MCP エンドポイント URL を記録します:

CWMCM0008I: The MCP server endpoint: http://localhost:9080/myMcpApp/mcp

Streamable HTTP トランスポート をサポートする任意の MCP クライアントをその URL に接続できます。

AI クライアントの接続

AI エージェントを MCP サーバーに接続するには、クライアントの設定に CWMCM0008I ログメッセージの MCP エンドポイント URL を指定します。例えば、MCP サーバーを IBM Bob に追加するには、~/.bob/settings/mcp.json ファイルを開き、mcpServers オブジェクトにエントリを追加します:

{
  "mcpServers": {
    "myApp": {
      "type": "streamable-http",
      "url": "http://localhost:9080/myMcpApp/mcp"
    }
  }
}

登録が完了すると、IBM Bob は次に会話が開始された際にツールを自動的に検出します。

MCP Inspector によるテスト

MCP Inspector は、ブラウザの UI から任意の MCP サーバー上のツールを参照・呼び出せるオープンソースのツールです。フルの AI エージェントを接続する前に、ツールが正しく登録されていることを確認する最も簡単な方法です。npm がインストールされている場合は、次のコマンドを実行してください:

npx @modelcontextprotocol/inspector

MCP エンドポイント URL を指定し、UI を使ってツールの一覧表示、呼び出し、生の JSON-RPC メッセージの検査が行えます。実際のワークフローでツールを使用する準備ができたら、MCP 対応の AI エージェントを同じエンドポイントに接続できます。

アノテーションによる MCP ツールの宣言

ビジネスロジックを AI アプリケーションに公開するには、CDI 管理 Bean 内の Java メソッドに @Tool アノテーションを追加して MCP ツールとして宣言します。

基本的な使用例

package com.example.mcp;

import org.mcpjava.server.tools.Tool;
import org.mcpjava.server.tools.ToolArg;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

@ApplicationScoped
public class WeatherTools {

    @Inject
    private WeatherClient weatherClient;

    @Tool(name = "getForecast",
          title = "Weather Forecast Provider",
          description = "Get the weather forecast for a location.")
    public String getForecast(
            @ToolArg(name = "latitude",  description = "Latitude of the location")  String latitude,
            @ToolArg(name = "longitude", description = "Longitude of the location") String longitude) {
        return weatherClient.getForecast(
                Double.parseDouble(latitude),
                Double.parseDouble(longitude),
                4,
                "temperature_2m,snowfall,rain,precipitation,precipitation_probability");
    }
}
@Tool アノテーションが付いたメソッドを機能で検出するには、クラスに @ApplicationScoped や @RequestScoped などの CDI スコープのアノテーションが必要です。

AI モデルはツールの description を読み取り、いつ、どのように呼び出すかを判断します。ツールを効果的に活用するために、明確で正確な説明を記述することが重要です。

@Tool の属性

属性 説明

name

AI がツールを呼び出す際に使用する識別子。デフォルトはメソッド名。

title

クライアント UI に表示されるオプションの人間が読みやすい表示名。デフォルトは name。

description

ツールの動作を説明します。AI モデルはこれを読んでいつ、どのように使用するかを判断します。

annotations

クライアントへの動作ヒントを提供するネストされた @Annotations 要素(ツールメタデータのヒント を参照)。

structuredContent

true の場合、戻り値は JSON としてシリアライズされ、非構造化コンテンツとともに構造化出力として含まれます。

@ToolArg の属性

属性 説明

name

JSON Schema に表示される引数名。-parameters でコンパイルしない限り必須。

description

AI が指定する値を理解するのに役立ちます。

required

引数をオプションにするには false に設定します。デフォルトは true。

defaultValue

AI が引数を指定しない場合に使用される文字列のデフォルト値。設定すると引数もオプションになります。

required = false、defaultValue が設定されている、またはパラメーター型が java.util.Optional<T>、OptionalInt、OptionalDouble、OptionalLong の場合、パラメーターはオプションとして扱われます。

import java.util.Optional;
import org.mcpjava.server.tools.Tool;
import org.mcpjava.server.tools.ToolArg;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class CatalogueTools {

    @Tool(name = "search", description = "Search the product catalogue.")
    public String search(
            @ToolArg(name = "query",    description = "Search terms")    String query,
            @ToolArg(name = "maxItems", description = "Maximum results",
                     required = false,  defaultValue = "10")             int maxItems,
            @ToolArg(name = "category", description = "Product category") Optional<String> category) {
        // category is empty when not provided by the AI
        return catalogue.search(query, maxItems, category.orElse("all"));
    }
}

カスタム JSON スキーマ

デフォルトでは、Liberty は Java 型に基づいて各ツール引数およびツールの構造化出力の JSON スキーマを生成します。io.openliberty.mcp.annotations の @Schema でタイプにアノテーションを付けることで、人間が読みやすい説明を生成されたスキーマに追加できます:

import io.openliberty.mcp.annotations.Schema;

@Schema(description = "A person with a home address and employer")
public record Person(String name, Address address, Company company) {}

@Schema はタイプ、フィールド、メソッド、または @ToolArg パラメーターに配置できます。生成されたスキーマが不十分な場合、value 属性に生の JSON スキーマ文字列を指定することで完全に置き換えられます。詳細はリファレンス・ドキュメントを参照してください。

カスタムデフォルト値の型

@ToolArg(defaultValue = "…​") は、String、プリミティブ型、列挙型に対してすぐに機能します。カスタム型の場合は、CDI Bean として DefaultValueConverter<T> を実装してください。Liberty が自動的に検出し、デフォルト値の文字列を指定した型に変換するために呼び出します:

import io.openliberty.mcp.annotations.DefaultValueConverter;
import jakarta.enterprise.context.ApplicationScoped;

public record DateRange(LocalDate start, LocalDate end) {}

@ApplicationScoped
public class DateRangeConverter implements DefaultValueConverter<DateRange> {
    @Override
    public DateRange convert(String defaultValue) {
        String[] parts = defaultValue.split("/");
        return new DateRange(LocalDate.parse(parts[0]), LocalDate.parse(parts[1]));
    }
}

CDI Bean を設定すれば、@ToolArg(defaultValue = "2024-01-01/2024-12-31") が DateRange で自動的に機能するようになります。同じ型に対して複数のコンバーターが存在する場合は、@jakarta.annotation.Priority の値が最も高いものが使用されます。

ツールメタデータのヒント

ネストされた @Annotations 要素を通じて、ツールの動作に関するヒントを MCP クライアントに伝えることができます。これらは Java アノテーションではなく、MCP プロトコルのメタデータフィールドであることに注意してください。

import org.mcpjava.server.tools.Tool;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class ConfigTools {

    @Tool(name = "readConfig",
          description = "Read the application configuration.",
          annotations = @Tool.Annotations(
                  readOnlyHint    = true,
                  destructiveHint = false,
                  idempotentHint  = true,
                  openWorldHint   = false))
    public String readConfig() {
        return configService.getCurrentConfig();
    }
}
ヒント デフォルト 意味

readOnlyHint

false

true — ツールはデータを変更しません。

destructiveHint

true

true — ツールはデータを破壊する可能性があります(readOnlyHint = false の場合のみ意味があります)。

idempotentHint

false

true — 同じ引数でツールを繰り返し呼び出しても、追加の効果はありません。

openWorldHint

true

true — ツールはアプリケーション外部のシステムと連携する可能性があります。

コンテンツオブジェクトの返却

ツールメソッドは String、POJO オブジェクト(JSON にシリアライズ)、または org.mcpjava.server.content パッケージの型付きコンテンツオブジェクトを返せます:https://www.javadoc.io/doc/org.mcpjava/mcp-server-api/latest/org/mcpjava/server/content/TextContent.html[TextContent]、https://www.javadoc.io/doc/org.mcpjava/mcp-server-api/latest/org/mcpjava/server/content/ImageContent.html[ImageContent]、https://www.javadoc.io/doc/org.mcpjava/mcp-server-api/latest/org/mcpjava/server/content/AudioContent.html[AudioContent]、https://www.javadoc.io/static/org.mcpjava/mcp-server-api/1.0.0/org/mcpjava/server/content/EmbeddedResource.html[EmbeddedResource]、https://www.javadoc.io/static/org.mcpjava/mcp-server-api/1.0.0/org/mcpjava/server/content/ResourceLink.html[ResourceLink]。

ツールレスポンス全体をきめ細かく制御するには、https://www.javadoc.io/doc/org.mcpjava/mcp-server-api/latest/org/mcpjava/server/tools/ToolResponse.html[ToolResponse] を直接返します。これにより、例外をスローすることなく AI にビジネスロジックエラーを通知することもできます:

import org.mcpjava.server.tools.Tool;
import org.mcpjava.server.tools.ToolArg;
import org.mcpjava.server.tools.ToolResponse;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class CatalogueTools {

    @Tool(name = "lookup", description = "Lookup an item.")
    public ToolResponse lookup(@ToolArg(name = "id", description = "Item ID") String id) {
        try {
            String result = catalogue.findById(id);
            return ToolResponse.ofText(result);
        } catch (NotFoundException e) {
            return ToolResponse.ofError("Item not found: " + id);
        }
    }
}

カスタムレスポンスエンコーディング

ツールメソッドから POJO を返すと、デフォルトで JSON にシリアライズされます。型の変換方法を正確に制御する必要がある場合は、https://www.javadoc.io/doc/org.mcpjava/mcp-server-api/latest/org/mcpjava/server/ContentEncoder.html[ContentEncoder<T>] CDI Bean を登録してください。getType() を実装して処理する型を宣言し、encode() を実装して ContentBlock を生成します:

import org.mcpjava.server.ContentEncoder;
import org.mcpjava.server.content.ContentBlock;
import org.mcpjava.server.content.TextContent;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;

@ApplicationScoped
public class PersonContentEncoder implements ContentEncoder<Person> {

    private static final Jsonb jsonb = JsonbBuilder.create();

    @Override
    public Class<Person> getType() {
        return Person.class;
    }

    @Override
    public ContentBlock encode(Person person) {
        // Custom formatting — e.g. redact sensitive fields before returning to the AI
        Person redacted = new Person(person.name(), "[REDACTED]", person.age());
        return TextContent.of(jsonb.toJson(redacted));
    }
}

ToolResponse 全体を制御する必要がある場合(例えば、失敗したビジネス結果をツールエラーにマッピングするなど)は、代わりに io.openliberty.mcp.tools.ToolResponseEncoder の ToolResponseEncoder<T> を実装してください。同じ型に対して両方が登録されている場合、ToolResponseEncoder が優先されます。同種のエンコーダーが複数の型にマッチする場合は、@jakarta.annotation.Priority の値が最も高いものが使用されます。

特殊なツールメソッドパラメーター

いくつかのパラメーター型は、ツールメソッドで宣言された場合に Liberty ランタイムによって自動的に注入されます。これらは AI によって提供されることはありません。

キャンセル処理

長時間実行されるツールは Cancellation パラメーターを受け取り、クライアントがキャンセルを要求したかどうかを定期的に確認する必要があります。cancellation.check().isRequested() を呼び出し、キャンセルが検出された場合は Cancellation.OperationCancelledException をスローします:

import org.mcpjava.server.Cancellation;
import org.mcpjava.server.tools.Tool;
import org.mcpjava.server.tools.ToolArg;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class DataTools {

    @Tool(name = "processDataset",
          title = "Process Large Dataset",
          description = "Processes a dataset in chunks. Can be cancelled by the client.")
    public String processDataset(
            @ToolArg(name = "datasetId", description = "ID of the dataset to process") String datasetId,
            Cancellation cancellation) throws InterruptedException {

        List<String> results = new ArrayList<>();
        for (String chunk : dataService.getChunks(datasetId)) {
            // Check for cancellation before processing each chunk
            if (cancellation.check().isRequested()) {
                throw new Cancellation.OperationCancelledException();
            }
            results.add(process(chunk));
        }
        return results.toString();
    }
}
キャンセル処理ではセッション ID と認証済みユーザーの両方を検証するため、別のユーザーが他のユーザーの実行中のツール呼び出しをキャンセルすることはできません。

McpRequest

McpRequest パラメーターは、リクエスト ID、セッション ID、プロトコルバージョン、クライアント機能など、現在のリクエストに関する情報へのアクセスを提供します。監査ログやトレースの相関に役立ちます:

import org.mcpjava.server.McpRequest;
import org.mcpjava.server.tools.Tool;
import org.mcpjava.server.tools.ToolArg;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class AuditTools {

    @Tool(name = "auditedSearch", description = "Search with audit logging.")
    public String auditedSearch(
            @ToolArg(name = "query", description = "Search query") String query,
            McpRequest request) {

        logger.info("Tool call [" + request.id() + "] session=" + request.sessionId().orElse("stateless")
                + " protocol=" + request.protocolVersion());

        return searchService.search(query);
    }
}

McpRequest は request.metadata() を通じてリクエストの _meta フィールドも公開しており、クライアントはコストバジェットヒント、レート制限ディレクティブ、相関 ID などのベンダー定義のコンテキストを渡すために使用できます。

非同期ツールの実行

ツールメソッドは CompletionStage<T> を返すことで、呼び出し中にスレッドを保持することなく非同期で実行できます。戻り値の型 T は同期ツールと同じルールに従います:

特殊なパラメーター Cancellation および McpRequest は非同期ツールメソッドでもサポートされています。
import java.util.concurrent.CompletionStage;
import org.mcpjava.server.tools.Tool;
import org.mcpjava.server.tools.ToolArg;
import jakarta.enterprise.concurrent.ManagedExecutorService;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class RemoteTools {

    @jakarta.annotation.Resource
    ManagedExecutorService executor;

    @Tool(name = "fetchRemoteData",
          description = "Fetch data from a remote service asynchronously.")
    public CompletionStage<String> fetchRemoteData(
            @ToolArg(name = "url", description = "URL to fetch") String url) {
        return executor.supplyAsync(() -> remoteClient.fetch(url));
    }
}

デフォルトでは、非同期ツールの実行は 30 秒 でタイムアウトします。アプリケーションごとにこの制限を設定できます。詳細は MCP サーバーの設定 を参照してください。

ToolManager によるプログラム的なツール登録

アノテーションベースの宣言に加えて、ToolManager CDI Bean(io.openliberty.mcp.tools.ToolManager)を使用してランタイム時にプログラム的にツールを登録できます。利用可能なツールのセットが、オプションの外部サービスに到達可能かどうかなど、実行時の条件に依存する場合に便利です。

ToolManager を注入し、CDI の Startup イベントを監視することでアプリケーション起動時にツールを登録します:

import io.openliberty.mcp.tools.ToolManager;
import org.mcpjava.server.tools.ToolResponse;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.event.Startup;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;

@ApplicationScoped
public class WeatherToolRegistrar {

    @Inject
    ToolManager toolManager;

    @Inject
    Instance<WeatherClient> weatherClientInstance;

    private void registerTools(@Observes Startup startup) {
        if (weatherClientInstance.isResolvable()) {
            WeatherClient weatherClient = weatherClientInstance.get();

            toolManager.newTool("getForecast")
                    .setTitle("Weather Forecast Provider")
                    .setDescription("Get weather forecast for a location")
                    .addArgument("latitude",  "Latitude of the location",  true, Double.class)
                    .addArgument("longitude", "Longitude of the location", true, Double.class)
                    .setHandler(args -> {
                        Double lat = (Double) args.args().get("latitude");
                        Double lon = (Double) args.args().get("longitude");
                        String result = weatherClient.getForecast(lat, lon, 4,
                                "temperature_2m,snowfall,rain,precipitation,precipitation_probability");
                        return ToolResponse.ofText(result);
                    })
                    .register();
        }
    }
}

ToolManager で登録されたツールと @Tool で宣言されたツールは、同じ MCP エンドポイント上で共存します。また、ランタイム時に toolManager.removeTool("name") を呼び出してツールの登録を解除することもできます。

ロールベースのアクセス制御による MCP ツールのセキュリティ保護

標準の Jakarta Security アノテーションを使用して、認証済みの呼び出し元がどのツールを呼び出せるかを制限します。

個々のツールメソッドまたは CDI Bean クラスに @RolesAllowed、@PermitAll、または @DenyAll を適用します。クラスレベルで設定すると、そのクラスのすべてのツールメソッドがアノテーションを継承します。メソッドレベルのアノテーションはクラスレベルのアノテーションを上書きします:

import org.mcpjava.server.tools.Tool;
import org.mcpjava.server.tools.ToolArg;
import jakarta.annotation.security.DenyAll;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import jakarta.enterprise.context.ApplicationScoped;

// Class-level @RolesAllowed — all methods in this bean require the Admins role
// unless overridden by a method-level annotation
@ApplicationScoped
@RolesAllowed("Admins")
public class BookShopAdminTools {

    // Method-level @RolesAllowed overrides the class-level annotation
    @RolesAllowed("Moderators")
    @Tool(name = "addBook", description = "Add a new book to the catalogue.")
    public String addBook(
            @ToolArg(name = "bookCode", description = "Unique code for the book") String bookCode) {
        return catalogueService.addBook(bookCode);
    }

    // Inherits class-level @RolesAllowed("Admins")
    @Tool(name = "banUser", description = "Ban a user from the platform.")
    public String banUser(
            @ToolArg(name = "userName", description = "Name of the user to ban") String userName) {
        return adminService.banUser(userName);
    }
}

// Class-level @PermitAll — all tools in this bean are publicly accessible
@ApplicationScoped
@PermitAll
public class BookShopPublicTools {

    @Tool(name = "listBooks", description = "List available books.")
    public String listBooks() {
        return catalogueService.listAll();
    }
}
  • tools/list レスポンスには、呼び出し元がアクセスできるツールのみが含まれます。

  • 保護されたツールへの未認証リクエストは HTTP 401 を返します。

  • 必要なロールを持たない認証済みリクエストは HTTP 403 を返します。

MCP サーバーの設定

server.xml ファイルの <mcp> 要素を使用すると、アプリケーションごとに MCP エンドポイントの動作をカスタマイズできます。

サーバーの説明とメタデータ

MCP 初期化時に、サーバーはサーバー名、バージョン、説明を含む serverInfo ブロックをクライアントに送信します。これは MCP クライアント UI に表示され、ユーザーが接続しているサーバーを識別するのに役立ちます。ネストされた <info> サブ要素を使用して設定します:

<application location="myMcpApp.war">
    <mcp>
        <info name="Weather Service"
              version="2.0"
              description="Provides real-time weather forecast tools."/>
    </mcp>
</application>

ステートレスモード

デフォルトでは、mcp-1.0 はセッションを維持して同じクライアントからのリクエストを関連付けます。リクエストが異なるサーバーインスタンスにルーティングされる可能性がある水平スケールやクラスター環境では、ステートレスモードを有効にしてこのセッションのアフィニティを除去します:

<application location="myMcpApp.war">
    <mcp stateless="true"/>
</application>

ステートレスモードでは、各リクエストは呼び出し間でのクライアントごとの状態を持たず、独立して処理されます。ただし、ステートレスモードではツール呼び出しのキャンセルなど、セッション追跡または独立した HTTP リクエストの関連付けに依存する MCP の機能が無効になります。

非同期ツールのタイムアウト

デフォルトでは、非同期ツールの実行は 30 秒 に制限されています。長時間実行される操作を行うツールの場合は、asyncTimeout 属性を使用してこの制限を増やします。値には Liberty の標準の期間フォーマット(例:30s、2m、1h)を使用します:

<application location="myMcpApp.war">
    <mcp asyncTimeout="2m"/>
</application>

サポートされる MCP プロトコルバージョン

mcp-1.0 の機能は以下の仕様バージョンをサポートしており、接続時にクライアントと自動的にネゴシエーションされます:

MCP サーバーメトリクスの監視

mcp-1.0 の機能は、Liberty の既存の可観測性スタックを使用してツール呼び出しのスループット、実行時間、セッションのライフサイクルを監視できる運用メトリクスをエクスポートします。

server.xml ファイルで mcp-1.0 と並べて monitor-1.0 を追加します。オプションで、メトリクスを OpenTelemetry コレクターにエクスポートするために mpTelemetry-2.1 を追加します:

<featureManager>
    <feature>servlet-6.0</feature>
    <feature>cdi-4.0</feature>
    <feature>mcp-1.0</feature>
    <feature>monitor-1.0</feature>
    <!-- Optional: export to OpenTelemetry -->
    <feature>mpTelemetry-2.1</feature>
</featureManager>

MCP に関する OpenTelemetry セマンティック規約 に準拠した 2 つのメトリクスがエクスポートされます:

mcp.server.operation.duration(ヒストグラム、秒)

各 MCP 操作(ツール呼び出し、一覧リクエスト、初期化)の実行時間を記録します。tools/call 操作の場合、gen_ai.tool.name 属性は呼び出されたツールを識別します。エラーが発生した場合は error.type 属性が設定されます。

mcp.server.session.duration(ヒストグラム、秒)

各 MCP セッションの実行時間を記録します(ステートフルモードのみ)。セッションがエラーで終了した場合は error.type 属性が設定されます。

OpenTelemetry が利用できない環境では、メトリクスは JMX 経由でもアクセスできます。詳細については MicroProfile Telemetry のドキュメント を参照してください。

マルチモジュール MCP アプリケーション(EAR デプロイメント)

Liberty は複数の WAR モジュールを含む EAR として MCP アプリケーションをデプロイすることをサポートしています。MCP ツールを含む各 WAR は独自の独立した MCP エンドポイントを取得し、ツール、エンコーダー、セッションはモジュール間で完全に分離されます。

各 <mcp> 要素の moduleName 属性を使用して、EAR 内の特定の WAR をターゲットにします:

<application location="myMcpApp.ear">
    <mcp path="/mcp"           moduleName="catalogue"/>
    <mcp path="/reporting-mcp" moduleName="reporting"/>
</application>

これにより 2 つの独立したエンドポイントが生成されます:

  • http://localhost:9080/catalogue/mcp

  • http://localhost:9080/reporting/reporting-mcp

各モジュールは起動時に独自の CWMCM0008I メッセージもログに記録するため、メッセージログで各エンドポイントの URL を確認できます。

フィードバックと詳細情報

バグを発見した場合や追加機能を要望する場合は、https://github.com/OpenLiberty/open-liberty/issues/new/choose[Open Liberty の GitHub リポジトリーにイシューを作成してください]。

Model Context Protocol の詳細については、https://modelcontextprotocol.io[MCP 公式ドキュメント] を参照してください。

Stack Overflow で質問する