# tools/list の出し方

Forecall が採点する JSON、受け付ける形と上限、forecall dump や公式の SDK で MCP サーバーから取り出す方法を説明します。

Forecall が採点するのは、MCP サーバーが `tools/list` の要求に返すツールの一覧です。各ツールの `name`、`description`、`inputSchema` と、あれば `outputSchema` と `annotations` を読みます。AI エージェントがツールを選ぶ前に読むのがこの内容なので、点数もこれについて付けます。

## 受け付ける形

Web のリンターと CLI は、同じ 3 つの形を同じ上限で読みます。

- ツールの配列: `[{ "name": … }, …]`
- tools の配列を持つオブジェクト: `{ "tools": [ … ] }`
- JSON-RPC の応答: `{ "result": { "tools": [ … ] } }`

上限は 1 MB（1,048,576 バイト）、200 ツールです。

キーは MCP の通信形式の名前（camelCase）で書きます。`inputSchema`、`outputSchema`、`annotations.readOnlyHint` などです。`input_schema` のような snake_case のキーがあると、その場所と直し方を一覧にして断ります。Forecall は自動では直しません。採点するのは、サーバーが実際に送る内容そのものだからです。

## サーバーから取り出す

いちばん手早いのは `forecall dump` です。サーバーを起動するかサーバーにつなぎ、その `tools/list` を上の形で書き出します。

```sh
npx forecall dump -o tools.json -- npx -y @modelcontextprotocol/server-filesystem .
npx forecall dump -o tools.json https://example.com/mcp --header "Authorization: Bearer $TOKEN"
```

オプションは[CLI で採点する](https://forecall.dev/ja/docs/cli#dump)にあります。自分のクライアントを使うなら、MCP の SDK でサーバーにつなぎ、`tools/list` の結果を出力します。次の例は stdio でサーバーを起動します。命令と引数は、あなたのサーバーのものに置き換えてください。どちらも `{"tools": [...]}` を出力するので、ファイルに保存できます。

### TypeScript

公式の SDK（`@modelcontextprotocol/client`）では、`listTools()` が一覧のすべてのページを読みます。

```ts
import { Client } from "@modelcontextprotocol/client";
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";

const client = new Client({ name: "dump-tools", version: "1.0.0" });
await client.connect(
  new StdioClientTransport({
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-filesystem", "."],
  }),
);
const { tools } = await client.listTools();
console.log(JSON.stringify({ tools }, null, 2));
await client.close();
```

### Python

公式の SDK（`mcp` 2.x）の `list_tools()` は 1 ページずつ読むので、`next_cursor` をたどります。ツールは `by_alias=True` を付けて書き出してください。付けないと `input_schema` のような snake_case のキーで書き出され、Forecall はそれを断ります。

```python
import asyncio
import json

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.types import PaginatedRequestParams


async def main():
    server = StdioServerParameters(
        command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "."]
    )
    async with stdio_client(server) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools, cursor = [], None
            while True:
                params = PaginatedRequestParams(cursor=cursor) if cursor else None
                result = await session.list_tools(params=params)
                # by_alias=True writes the MCP names (inputSchema, not input_schema).
                tools += [t.model_dump(mode="json", by_alias=True, exclude_none=True) for t in result.tools]
                cursor = result.next_cursor
                if cursor is None:
                    break
            print(json.dumps({"tools": tools}, indent=2, ensure_ascii=False))


asyncio.run(main())
```

## 採点する

JSON を[リンター](https://forecall.dev/ja/lint)に貼るか、[CLI](https://forecall.dev/ja/docs/cli) で手元のファイルを採点します。

```sh
npx forecall lint tools.json
```

まだ公開していないツール定義は貼らないでください。結果は URL を知っている人なら誰でも見られます。`forecall lint` はどこにも送りません。
