Skip to main content
Glama

Fitter — AIエージェント向けWebデータ

MCP Toplist

Release License: MIT Go Reference Sponsor

Fitterは、あらゆるWebサイトやAPIを宣言的に構造化JSONに変換します。 1つのJSON/YAML設定で、データの場所(HTTPリクエスト、ヘッドレスブラウザ、ファイル、静的値)と抽出内容(JSONパス、CSSセレクタ、XPath)を記述します。コードも、壊れやすいスクレイピングスクリプトも不要です。

🚀 ブラウザで試す — WebAssemblyにコンパイルされた本物のエンジン: ライブ例、ビジュアル設定ビルダー、インストール不要。

設定はプレーンなデータであるため、LLMがそれらを作成できます。組み込みのMCPサーバーを使用すると、Claude Code、Claude Desktop、または任意のMCPクライアントが、オンデマンドでマシン上でスクレイピングパイプラインを作成・実行できます。

「タイトルとスコア付きのHackerNewsトップ5ストーリーを取得して」 → モデルがfitter設定を作成し、検証し、ローカルで実行して、クリーンなJSONを取得します。

1つのエンジン、5つの使い方:

🤖 Fitter MCP

MCPサーバーがfitterをClaude Code、Claude Desktop、および任意のMCPクライアントに公開します

🧠 Fitter Agent

AI搭載CLI: 自然言語 → 設定 → 実行結果

🖥 Fitter CLI

テスト/デバッグ/ホーム用途で設定をローカル実行

📦 Fitter Lib

独自のGoプログラムにエンジンを組み込む

⚙️ Fitter

スケジューリングと通知を備えた長時間実行サービスモード

なぜAIエージェントにfitterなのか?

  • 宣言的で監査可能 — エージェントは、読み取り・保存・再実行が可能な設定を生成し、使い捨てコードではありません

  • ローカルファースト — すべての取得はマシン上で行われます。サードパーティのスクレイピングAPI、キー、リクエストごとの課金はありません

  • バッテリー同梱 — HTTPクライアント、ヘッドレスブラウザ(Playwright/Chromium/Docker)、JSON/HTML/XML/XPath/PDF解析、ページネーション、キャッシュ参照、ホストレート制限 — 単一の静的バイナリに

  • 再利用可能 — 今日エージェントが作成したものは、明日のcronジョブやサービス設定になります

fitter demo — declarative config to structured JSON

Fitter_MCPの使い方

Fitter MCPは、Model Context Protocolサーバー(stdioトランスポート)であり、任意のMCPクライアント(Claude Code、Claude Desktop、IDEアシスタント、カスタムエージェント)がFitter設定を実行し、構造化JSONを取得できるようにします。

クイックスタート(Claude Desktop — ワンクリック)

リリースページからfitter-mcp-<os>-<arch>.mcpbをダウンロードして開くだけで、Claude Desktopがサーバーを自動的にインストールします。

クイックスタート(Claude Code)

# 1. get the binary: download fitter_mcp_<version>-<os>-<arch> from the release page
#    https://github.com/PxyUp/fitter/releases — or build it from source:
go build -o fitter_mcp ./cmd/mcp

# 2. register it once, available in every project
claude mcp add fitter -s user -- "$(pwd)/fitter_mcp"

あとは次のように尋ねるだけです:

fitterを使って、タイトルとスコア付きのHackerNewsトップ5ストーリーを取得して

モデルはfitter_config_referenceを呼び出し、設定を作成し、必要に応じてfitter_validate_configでチェックし、fitter_runで実行します — すべてのデータ取得はマシン上でローカルに行われます。既製のパイプラインとして、examples/config_morning_briefing.jsonを試してください:

fitterでexamples/config_morning_briefing.jsonを実行して、ブリーフィングを教えて

Claude Desktopに登録

{
  "mcpServers": {
    "fitter": {
      "command": "/path/to/fitter_mcp"
    }
  }
}

ブラウザサポート(Playwright)

.mcpbバンドルとネイティブバイナリにはブラウザは含まれていません。HTTP、静的、ファイルコネクタはすぐに動作しますが、ブラウザ設定(playwrightコネクタ)にはPlaywrightのブラウザが必要です。入手方法はいくつかあります:

  • 初回使用時(ネイティブバイナリ / .mcpb): playwrightコネクタで"install": trueを設定します — fitterは初回使用時に、組み込みのplaywright-goバージョンに一致するドライバーとブラウザをダウンロードします(一度きり、キャッシュされます)。そのため、別途インストール手順は不要です。

  • 事前に(ネイティブ、オプション): 初回ダウンロードを避けるために、fitterがビルドされているのと同じplaywright-goバージョンでブラウザを事前にインストールします(go.modを確認、現在はv0.6100.0):

    go run github.com/mxschmitt/playwright-go/cmd/playwright@v0.6100.0 install
    # Linux: append --with-deps to also install the required OS libraries

    バージョンはgo.modと正確に一致する必要があります — playwright-goは不一致のドライバーでは実行を拒否します。その後、"install": trueなしで設定を実行します。

  • Docker: Chromium、Firefox、WebKitがプリインストールされたghcr.io/pxyup/fitter-mcp:playwrightイメージを使用します("install": trueは不要)。

ツール

Tool

Description

fitter_run

インラインで渡されたFitter設定(JSONまたはYAML文字列)を実行し、抽出したデータをJSONとして返します。オプションのinput値を受け付け、設定内で{{{FromInput=.}}} / {{{FromInput=json.path}}}として利用できます。

fitter_run_file

fitter_runと同じですが、ローカルの.json/.yamlファイルから設定を読み取ります。

fitter_run_url

fitter_runと同じですが、HTTP(S) URL(例: raw GitHubリンク)から設定をダウンロードします。

fitter_inspect_url

URLを取得し、コンパクトな構造の概要と候補セレクタ/パス(JSONの場合はgjsonパス、HTMLの場合は繰り返し要素/リスト行セレクタ)を返します。これにより、モデルはセレクタを推測してnullを取得する代わりに、最初の試行で設定を作成できます。クライアントレンダリングされたSPAを検出し、ヘッドレスブラウザでrenderできます。読み取り専用 — 抽出は行いません。

fitter_validate_config

設定を実行せずに検証します(構造、response_type、コネクタのデータソース、モデル)。設定を反復処理する際に便利です。

fitter_config_reference

設定形式全体(コネクタ、パーサー、モデル/フィールドスキーマ、プレースホルダー、通知、参照、制限)の簡潔なリファレンスを作業例付きで返します。モデルは外部ドキュメントなしで設定を作成できます。

このリファレンスは、リソースをサポートするクライアント向けにMCPリソースfitter://config-referenceとしても公開されています。

設定形式はFitter_CLIとまったく同じです。トップレベルのオブジェクトにはitem(必須)、limitsreferencesがあります。通知も機能します(結果はさらにhttp/telegram/redis/file/consoleにプッシュされます)。trigger_confighttp_serverはサービスモード専用で、MCP呼び出しでは無視されます。

リモート/ホストモード(ストリーミングHTTP)

デフォルトではfitter_mcpはstdioで通信します。代わりにストリーミングHTTPトランスポートを提供するには--httpを渡します — 共有チームサーバー、コンテナ、または任意のリモートデプロイメント向けです:

# serve MCP at http://<host>:8080/mcp (health probe at /healthz)
FITTER_MCP_AUTH_TOKEN=my-secret fitter_mcp --http :8080

# register the remote endpoint in Claude Code
claude mcp add --transport http fitter http://localhost:8080/mcp --header "Authorization: Bearer my-secret"
  • --http <addr>(環境変数FITTER_MCP_HTTP_ADDR)— リッスンアドレス。空の場合はstdioモード

  • FITTER_MCP_AUTH_TOKEN — 設定すると、すべての/mcpリクエストはAuthorization: Bearer <token>を送信する必要があります。設定しない場合、エンドポイントは認証なしになるため、localhostにバインドするか、プロキシの背後に置いてください

  • --stateless(環境変数FITTER_MCP_STATELESS=true)— セッションごとの状態がないため、レプリカをスティッキーセッションなしでロードバランサーの背後に配置できます

サーバーはSIGINT/SIGTERMでグレースフルシャットダウンします。

Docker

スリムなマルチアーキテクチャイメージ(linux/amd64 + linux/arm64)が各リリースに同梱されています:

# hosted HTTP mode
docker run --rm -p 8080:8080 \
  -e FITTER_MCP_HTTP_ADDR=:8080 \
  -e FITTER_MCP_AUTH_TOKEN=my-secret \
  ghcr.io/pxyup/fitter-mcp:latest

# or stdio mode, spawned by the MCP client
claude mcp add fitter -s user -- docker run --rm -i ghcr.io/pxyup/fitter-mcp:latest

スリムイメージにはfitterバイナリとCA証明書のみが含まれています。サーバー/静的/ファイルコネクタは動作しますが、ブラウザコネクタ(chromium/docker/playwright)は動作しません。

ブラウザベースの設定にはplaywrightバリアントを使用します。これはPlaywrightとChromium、Firefox、WebKitをバンドルしています(fitterがビルドされているplaywright-goバージョンに一致するため、設定で"install": trueは不要です):

docker run --rm -i ghcr.io/pxyup/fitter-mcp:playwright        # stdio mode
# per-release tag: ghcr.io/pxyup/fitter-mcp:vX.Y.Z-playwright

これはDockerfile.mcp-playwrightからビルドされています。--build-arg PLAYWRIGHT_BROWSERS=chromiumでビルドすると、より小さなChromiumのみのイメージになります。

DockerでのOAuth2アカウント

両方のイメージにはfitter_cliが同梱されているため、一度きりのOAuth2ログインをコンテナ内で実行できます。トークンを/tokensにマウントされたボリューム(イメージ内で事前に作成された書き込み可能なディレクトリ)に保存し、MCPサーバーと共有します:

# one-time login, device flow: no ports needed — open the printed url on any device
docker run --rm -it -v fitter-tokens:/tokens --entrypoint fitter_cli \
  ghcr.io/pxyup/fitter-mcp:latest \
  auth --provider github --client-id <ID> --client-secret <SECRET> --token-file /tokens/github.json

# or browser flow (device flow not enabled for the app): publish the callback port and
# bind on 0.0.0.0 so the published port reaches the listener; the browser still visits 127.0.0.1
docker run --rm -it -p 8988:8988 -e FITTER_AUTH_LISTEN=0.0.0.0 \
  -v fitter-tokens:/tokens --entrypoint fitter_cli ghcr.io/pxyup/fitter-mcp:latest \
  auth --provider github --client-id <ID> --client-secret <SECRET> --token-file /tokens/github.json

# then run the MCP server with the same volume; configs reference "token_file": "/tokens/github.json"
# stdio mode (spawned by the MCP client, no port):
docker run --rm -i -v fitter-tokens:/tokens ghcr.io/pxyup/fitter-mcp:latest
# hosted HTTP mode (MCP endpoint on 8080, like the run examples above):
docker run --rm -p 8080:8080 -v fitter-tokens:/tokens \
  -e FITTER_MCP_HTTP_ADDR=:8080 \
  -e FITTER_MCP_AUTH_TOKEN=my-secret \
  ghcr.io/pxyup/fitter-mcp:latest

注: 8988は一度きりのブラウザフローログイン専用です。MCPサーバー自体はstdioモードではポートを必要とせず、ホストHTTPモードでは8080のみ必要です。

Dockerでのログイン済みブラウザセッション

ブラウザセッションにはplaywrightイメージが必要です(スリム版にはブラウザがありません)。一度きりのヘッド付きログインにはディスプレイが必要なため、ホスト上で実行し、セッションディレクトリをコンテナにバインドマウントします(イメージは書き込み可能な/sessionsを事前に作成します):

# on the host: log in once, save the session
fitter_cli browser-login --url https://example.com/login --storage-state ~/.fitter/sessions/example.json

# run the MCP server with the sessions dir mounted; configs reference "storage_state_file": "/sessions/example.json"
docker run --rm -i -v ~/.fitter/sessions:/sessions ghcr.io/pxyup/fitter-mcp:playwright

バインドマウント(名前付きボリュームではなく)を使用してください。コンテナは毎回の実行後に更新されたクッキーを書き戻すため、ホスト側のコピーは最新の状態を保ち、いつでもbrowser-loginで再拡張できます。

ボリュームはサーバーが書き込み可能な状態を維持する必要があります。ローテーションされたリフレッシュトークンは、リフレッシュのたびに書き戻されます。

環境変数

  1. FITTER_PLUGINS - string[""] - プラグインフォルダのパス、Fitter/Fitter_CLIの--pluginsフラグと同じ

  2. FITTER_MCP_HTTP_ADDR - string[""] - リモートモードのリッスンアドレス、--httpと同じ

  3. FITTER_MCP_AUTH_TOKEN - string[""] - HTTPエンドポイントを保護するベアラートークン

  4. FITTER_MCP_STATELESS - bool[false] - ステートレスHTTPトランスポート、--statelessと同じ

レシピ

Complete, tested configs showing the main patterns. All of them run unchanged via Fitter_MCP (fitter_run_file), Fitter_CLI or the library — more in examples/.

APIのないページをスクレイピングし、APIのあるページから情報を補完する

GitHub trendingには公式APIがありません。HTMLからリポジトリのスラッグをスクレイピングし(html_attributehrefを読み取ります)、その後{PL}を使って各リポジトリをGitHub REST APIに展開します:

examples/config_github_trending.json

{
  "item": {
    "connector_config": {
      "response_type": "HTML",
      "url": "https://github.com/trending",
      "server_config": { "method": "GET", "headers": { "User-Agent": "Mozilla/5.0 (fitter demo)" } }
    },
    "model": {
      "array_config": {
        "root_path": "article.Box-row h2 a",
        "length_limit": 5,
        "item_config": {
          "field": {
            "type": "string",
            "html_attribute": "href",
            "generated": { "model": {
              "type": "object",
              "connector_config": {
                "response_type": "json",
                "url": "https://api.github.com/repos{PL}",
                "server_config": { "method": "GET", "headers": { "User-Agent": "fitter-demo" } },
                "null_on_error": true
              },
              "model": { "object_config": { "fields": {
                "repo": { "base_field": { "type": "string", "path": "full_name" } },
                "stars": { "base_field": { "type": "int", "path": "stargazers_count" } },
                "language": { "base_field": { "type": "string", "path": "language" } }
              } } }
            } }
          }
        }
      }
    }
  },
  "limits": { "host_request_limiter": { "api.github.com": 2 } }
}
[{"repo": "block/buzz", "stars": 6214, "language": "Rust"}, {"repo": "koala73/worldmonitor", "stars": 71179, "language": "TypeScript"}]

式を使ってJSONフィールドで結合する

配列の項目がオブジェクトの場合、結合キーはその中にあります。{{{FromExp=...}}}(現在の項目fResに対するexpr-lang)で取り出します。書籍検索→著者詳細、検索クエリはinputで指定します:

examples/config_book_authors.json

"url": "https://openlibrary.org/authors/{{{FromExp=fromJSON(fRes).author_key[0]}}}.json"
./fitter_cli --path=examples/config_book_authors.json --input=dune
[{"title": "Dune", "year": 1965, "author": {"name": "Frank Herbert", "born": "8 October 1920", "died": "11 February 1986"}}]

結果をローカルファイルに書き込む

file_storage生成フィールドは、フィールドを書き込みに変換します。上位5つの暗号通貨をCSVに追加し、各項目を1行にします。裸の{{{json.path}}}プレースホルダーは現在の項目を読み取ります。{HUMAN_INDEX}は1から始まるランクを刻印します(項目は並列で処理されるため、追加は完了順に配置されます。ランク列で並べ替えてください):

examples/config_crypto_csv.json

"file_storage": {
  "content": "{HUMAN_INDEX},{{{name}}},{{{current_price}}},{{{price_change_percentage_24h}}}\n",
  "file_name": "coins.csv",
  "path": "/tmp/fitter-report",
  "append": true
}
$ sort -n /tmp/fitter-report/coins.csv
1,Bitcoin,64778,-2.3
2,Ethereum,1881.01,-3.4
3,Tether,0.999265,0

PDFからテキストを抽出する

response_type: "pdf"は、取得したPDFをJSONドキュメントに変換します。{"text": "...", "pages": ["..."], "total_pages": N} — これにより、通常のJSONパス(textpages.0)や式が機能します。Bitcoinホワイトペーパー、ページ数、トリミングされたイントロ:

examples/config_pdf.json

{
  "item": {
    "connector_config": {
      "response_type": "pdf",
      "url": "https://bitcoin.org/bitcoin.pdf",
      "server_config": { "method": "GET" }
    },
    "model": {
      "object_config": {
        "fields": {
          "total_pages": { "base_field": { "type": "int", "path": "total_pages" } },
          "intro": {
            "base_field": {
              "type": "string",
              "path": "pages.0",
              "generated": {
                "calculated": {
                  "type": "string",
                  "expression": "trim(fRes[:100]) + \"...\""
                }
              }
            }
          }
        }
      }
    }
  }
}
{"intro": "Bitcoin: A Peer-to-Peer Electronic Cash SystemSatoshi Nakamotosatoshin@gmx.comwww.bitcoin.orgAbstrac...", "total_pages": 9}

情報収集の方法

  1. Server - 一部のAPIまたはHTTPリクエストからの応答を解析する(http.Clientの使用)

  2. Browser - chromium + docker + playwright/cypressを使用して実際のブラウザをエミュレートし、DOM情報を取得する

  3. Static - 静的文字列をデータとして解析する

解析可能な形式

  1. JSON - JSONを解析して特定の情報を取得する

  2. XML - XMLツリーを解析して特定の情報を取得する

  3. HTML - DOMツリーを解析して特定の情報を取得する

  4. XPath - DOMツリーを解析して特定の情報を取得するが、XPathによる

  5. PDF - PDFドキュメントからテキストを抽出する。コンテンツはJSON {"text": "...", "pages": ["..."], "total_pages": N}として公開されるため、textpages.0のような通常のJSONパスが機能する

ライブラリとして使用する

go get github.com/PxyUp/fitter
package main

import (
	"fmt"
	"github.com/PxyUp/fitter/lib"
	"github.com/PxyUp/fitter/pkg/config"
	"log"
	"net/http"
)

func main() {
	res, err := lib.Parse(&config.Item{
		ConnectorConfig: &config.ConnectorConfig{
			ResponseType:  config.Json,
			Url:           "https://random-data-api.com/api/appliance/random_appliance",
			ServerConfig: &config.ServerConnectorConfig{
				Method: http.MethodGet,
			},
		},
		Model: &config.Model{
			ObjectConfig: &config.ObjectConfig{
				Fields: map[string]*config.Field{
					"my_id": {
						BaseField: &config.BaseField{
							Type: config.Int,
							Path: "id",
						},
					},
					"generated_id": {
						BaseField: &config.BaseField{
							Generated: &config.GeneratedFieldConfig{
								UUID: &config.UUIDGeneratedFieldConfig{},
							},
						},
					},
					"generated_array": {
						ArrayConfig: &config.ArrayConfig{
							RootPath: "@this|@keys",
							ItemConfig: &config.ObjectConfig{
								Field: &config.BaseField{
									Type: config.String,
								},
							},
						},
					},
				},
			},
		},
	}, nil, nil, nil, nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.ToJson())
}

出力:

{
  "generated_array": ["id","uid","brand","equipment"],
  "my_id": 6000,
  "generated_id": "26b08b73-2f2e-444d-bcf2-dac77ac3130e"
}

lib.ParseCtx(ctx, ...)を使用してcontext.Contextを渡します。キャンセルすると進行中のフェッチ(HTTPリクエスト、ヘッドレスブラウザ、Dockerコンテナ)が中止され、デッドラインがエンドツーエンドで適用されます。lib.Parselib.ParseCtx(context.Background(), ...)と同等です。

Fitterの使い方

リリースページから最新版をダウンロード

またはローカルで:

go run cmd/fitter/main.go --path=./examples/config_api.json

引数

  1. --path - string[""] - Fitterの設定ファイルのパス

  2. --url - string[""] - Fitterの設定のURL

  3. --verbose - bool[false] - ログを有効にする

  4. --plugins - string[""] - Fitter用プラグインのパス

  5. --log-level - enum["info", "error", "debug", "fatal"] - ログレベルを設定する(verboseがtrueの場合のみ)

Fitter_CLIの使い方

リリースページから最新版をダウンロード

またはローカルで:

go run cmd/cli/main.go --path=./examples/cli/config_cli.json

引数

  1. --path - string[""] - Fitter_CLIの設定ファイルのパス

  2. --url - string[""] - Fitter_CLIの設定のURL

  3. --copy - bool[false] - 情報をクリップボードにコピーする

  4. --pretty - bool[true] - 読みやすい結果にする(コピーにも影響)

  5. --verbose - bool[false] - ログを有効にする

  6. --omit-error-pretty - bool[false] - prettyが無効な場合に純粋な値を提供する

  7. --plugins - string[""] - Fitter用プラグインのパス

  8. --log-level - enum["info", "error", "debug", "fatal"] - ログレベルを設定する(verboseがtrueの場合のみ)

  9. --input - string[""] - フォーマットのための入力値を指定する。例:--input=\""124"\" --input=124 --input='{"test": 5}'

./fitter_cli_${VERSION} --path=./examples/cli/config_cli.json --copy=true

fitter_cli auth — OAuth2アカウントを接続する

一度だけの対話型ログインで、oauth2コネクタ設定用の(リフレッシュ)トークンを保存します:

# device flow (default when the provider supports it): no callback, works headless
./fitter_cli_${VERSION} auth --provider github --client-id <ID> --client-secret <SECRET> --token-file ~/.fitter/tokens/github.json

# custom provider without preset
./fitter_cli_${VERSION} auth --auth-url https://.../authorize --token-url https://.../token --client-id <ID> --token-file ./token.json

引数:

  1. --provider - 既知のエンドポイントを持つプリセット:github|google|microsoft|gitlab|spotify

  2. --client-id / --client-secret - OAuth2アプリの認証情報(一部のデバイスフローはシークレットなしで動作します)

  3. --token-file - 受け取ったトークンを保存する場所(0600パーミッション)。oauth2.token_fileで同じパスを参照します

  4. --flow - auto(利用可能ならデバイス、それ以外はブラウザ)、device(URLにアクセスしてコードを入力)、またはbrowser(PKCEを使用したlocalhostコールバック、デフォルトポート8988 — アプリのコールバックURLとしてhttp://127.0.0.1:8988/callbackを登録)

  5. --scopes - カンマ区切りのスコープ

  6. --auth-url/--token-url/--device-auth-url/--auth-style - プリセットのないプロバイダー向けのエンドポイント上書き

  7. --port - int[8988] - ブラウザフローのコールバックポート(環境変数FITTER_AUTH_PORT)。デフォルトでは、プロバイダーに登録するコールバックURLはhttp://127.0.0.1:8988/callbackです

  8. --listen - ブラウザフローのバインドアドレス、デフォルトは127.0.0.1。コンテナ内では0.0.0.0に設定して、公開ポートがリスナーに到達するようにします(環境変数FITTER_AUTH_LISTEN

  9. --redirect-url - リスンアドレスと異なる場合にプロバイダーに登録するコールバックURL。例:Dockerポートマッピング(環境変数FITTER_AUTH_REDIRECT_URL

  10. --no-browser - 認証URLのみを表示する

Docker内で実行する場合:Docker内のOAuth2アカウントを参照してください。

ログイン後、コマンドはすぐに使用できるoauth2設定ブロックを出力します。コネクタはアクセストークンを自動的に更新し、ローテーションされたリフレッシュトークンをトークンファイルに書き戻すため、ログインは一度だけ必要です。

fitter_cli browser-login — 実際のログインセッションを再利用する

API/OAuthのないサイト向け:実際の(ヘッド付き)ブラウザウィンドウで手動で一度ログインします。パスワード、2FA、SSO、キャプチャを含むあらゆる認証方式が機能します。そして、storage_state_fileを介してヘッドレススクレイピング用にセッションを保存します:

./fitter_cli_${VERSION} browser-login --url https://example.com/login --storage-state ~/.fitter/sessions/example.json
# a browser window opens; log in, then press Enter in the terminal to save the session

引数:

  1. --url - 開くログインページ(必須)

  2. --storage-state - セッションを保存する場所(cookies + localStorage、0600パーミッション)。playwright.storage_state_fileで同じパスを参照します(必須)

  3. --browser - enum["Chromium", "FireFox", "WebKit"] デフォルトは"Chromium"。スクレイピング設定と同じ値を使用します。サイトがセッションをブラウザのフィンガープリントにバインドする場合があります

  4. --install - bool[false] - 最初にPlaywrightブラウザをインストールする

  5. --indexeddb - bool[false] - スナップショットにIndexedDBを含める(Firebase Authなど)

コマンドを再実行すると、既存の状態が最初に読み込まれるため、最初からログインしなくてもセッションを拡張/更新できます。スクレイピングコネクタも毎回実行後に更新されたクッキーを書き戻すため、定期的に使用されている限りセッションは維持されます。ディスプレイが必要です。Docker内では、このコマンドをホストで実行し、ファイルをマウントしてください。Docker内のブラウザセッションを参照してください。

例:

  1. Server版 HackerNews + Quotes + Guardian News - API + HTML + XPath解析を使用

  2. Chromium版 Guardian News + Quotes - HTML解析 + ブラウザエミュレーションを使用

  3. Docker版 Docker版: Guardian News + Quotes - HTML解析 + Dockerイメージからのブラウザを使用

  4. Playwright版 Playwright版: Guardian News + Quotes - HTML解析 + Playwrightフレームワークからのブラウザを使用

  5. Playwright版 Playwright版: England Cities + Weather - HTML + XPath解析 + Playwrightフレームワークからのブラウザを使用

  6. JSON版 ページネーションを生成 - 静的コネクタを使用してページネーション配列を生成

  7. Server版 現在時刻を取得 - URLから時刻を取得してフォーマットする

Fitter_Agentの使い方

Fitter Agentは、Claudeを使用して自然言語のリクエストをFitter設定に変換し、自動的に実行するAI搭載のCLIです。

リリースページから最新版をダウンロード

またはローカルで:

export ANTHROPIC_API_KEY=<your-anthropic-api-key>
go run cmd/agent/main.go

引数

  1. --api-key - string[""] - Anthropic APIキー。キーがシェル履歴に残らないように、ANTHROPIC_API_KEY環境変数を推奨します

  2. --model - string["claude-opus-4-8"] - 使用するClaudeモデル

  3. --effort - enum["low", "medium", "high", "xhigh", "max"] - 推論の努力量、デフォルトは"high"。より速く/安価な設定には下げ、より難しい抽出には上げます

  4. --verbose - bool[false] - ログを有効にする

  5. --log-level - enum["info", "error", "debug", "fatal"] - ログレベルを設定する

  6. --plugins - string[""] - Fitter用プラグインのパス

  7. --chromium-limit - uint[0] - 同時Chromiumインスタンス数を制限する

  8. --docker-limit - uint[0] - 同時Dockerコンテナ数を制限する

  9. --playwright-limit - uint[0] - 同時Playwrightインスタンス数を制限する

仕組み

┌─────────────────────────────────────────────────────────────────┐
│  1. User enters natural language request                       │
│     "Get top 5 HackerNews stories with titles and scores"      │
│                              ↓                                  │
│  2. Claude returns a config in a schema-constrained response   │
│                              ↓                                  │
│  3. Agent validates it; on failure the error is handed back    │
│     to Claude to repair (up to 3 attempts)                     │
│                              ↓                                  │
│  4. Agent displays config and asks for confirmation            │
│                              ↓                                  │
│  5. On confirmation, executes via lib.Parse()                  │
│                              ↓                                  │
│  6. Returns structured JSON result                             │
└─────────────────────────────────────────────────────────────────┘

設定の調整

エージェントは会話を保持するため、設定が生成された後は、リクエスト全体を言い直す代わりに、変更したいことを言うだけで済みます:

> Get top 3 HackerNews stories with titles and scores
refine> Only return 5 items and also include the article URL

newを使用すると、現在の設定を忘れて新しいセッションを開始します。

対話型REPLコマンド

  • help - ヘルプメッセージを表示

  • new/reset - 現在の設定を忘れて新しく開始

  • clear - 画面をクリア

  • exit/quit/q - エージェントを終了

セッション例

$ export ANTHROPIC_API_KEY=sk-ant-...
$ ./fitter_agent

╔══════════════════════════════════════════════════════════════╗
║           Fitter Agent - AI-Powered Data Extraction           ║
╚══════════════════════════════════════════════════════════════╝

Describe what you want to extract. Follow-up messages refine the
previous config. Type 'help' for commands.

> Get top 3 HackerNews stories with titles and scores

┌─ Generated Fitter Config ───────────────────────────────────────
{
  "item": {
    "connector_config": {
      "response_type": "json",
      "url": "https://hacker-news.firebaseio.com/v0/topstories.json",
      "server_config": { "method": "GET" }
    },
    "model": {
      "array_config": {
        "root_path": "@this",
        "length_limit": 3,
        "item_config": {
          "fields": {
            "id": { "base_field": { "type": "int" } },
            "story": {
              "base_field": {
                "type": "int",
                "generated": {
                  "model": {
                    "type": "object",
                    "connector_config": {
                      "response_type": "json",
                      "url": "https://hacker-news.firebaseio.com/v0/item/{PL}.json",
                      "server_config": { "method": "GET" }
                    },
                    "model": {
                      "object_config": {
                        "fields": {
                          "title": { "base_field": { "type": "string", "path": "title" } },
                          "score": { "base_field": { "type": "int", "path": "score" } }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
└──────────────────────────────────────────────────────────────────

Execute this config? [y/n]: y

┌─ Result ────────────────────────────────────────────────────────
[
  {
    "id": 46740029,
    "story": { "title": "Show HN: Open-source project", "score": 161 }
  },
  {
    "id": 46737630,
    "story": { "title": "Interesting article", "score": 237 }
  },
  {
    "id": 46735644,
    "story": { "title": "New technology release", "score": 192 }
  }
]
└──────────────────────────────────────────────────────────────────

> exit
Goodbye!

リクエスト例

Request

What it does

Get Bitcoin price from CoinGecko API

現在のBTC価格を取得

Scrape headlines from news.ycombinator.com with links

CSSセレクタを使用したHTMLスクレイピング

Get top 5 stories from HackerNews with titles

ネストされたAPI呼び出し

Fetch weather data from wttr.in for London

シンプルなAPI抽出

Scrape product names and prices from example.com

Webスクレイピング

サポートされている機能

エージェントは以下の設定を生成できます:

  • JSON APIs - GET/POSTメソッドを使用したREST API

  • HTML Scraping - CSSセレクタベースの抽出

  • XPath Scraping - XPathベースの抽出

  • Nested API Calls - リスト内の各項目の詳細を取得

  • Browser Emulation - JSレンダリングページ用のPlaywright

  • Formatted Fields - プレースホルダー付きのURLテンプレート

  • Array Limiting - 結果をN項目に制限

設定

コネクタ

データを取得する方法です

type ConnectorConfig struct {
    ResponseType ParserType `json:"response_type" yaml:"response_type"`
    Url          string     `json:"url" yaml:"url"`
    Attempts     uint32     `json:"attempts" yaml:"attempts"`
    
    NullOnError bool `yaml:"null_on_error" json:"null_on_error"`
    
    StaticConfig          *StaticConnectorConfig      `json:"static_config" yaml:"static_config"`
    IntSequenceConfig     *IntSequenceConnectorConfig `json:"int_sequence_config" yaml:"int_sequence_config"`
    ServerConfig          *ServerConnectorConfig      `json:"server_config" yaml:"server_config"`
    BrowserConfig         *BrowserConnectorConfig     `yaml:"browser_config" json:"browser_config"`
    PluginConnectorConfig *PluginConnectorConfig      `json:"plugin_connector_config" yaml:"plugin_connector_config"`
    ReferenceConfig       *ReferenceConnectorConfig   `yaml:"reference_config" json:"reference_config"`
    FileConfig            *FileConnectorConfig        `json:"file_config" yaml:"file_config"`
}
  • NullOnError[false] - true に設定すると、すべてのエラーが無視されます

  • ResponseType - enum["HTML", "json", "xpath", "XML", "pdf"] - コネクタからデータがどの形式で取得されるか

  • Attempts - コネクタによるデータ取得を試行する回数

  • Url - リクエストするアドレスを指定します。重要: 親の値を文字列として注入 することができます https://api.open-meteo.com/v1/forecast?latitude={{{latitude}}}&longitude={{{longitude}}}&hourly=temperature_2m&forecast_days=1

設定は次のいずれかになります:

例:

{
  "response_type": "xpath",
  "attempts": 3,
  "url": "https://openweathermap.org/find?q={PL}",
  "browser_config": {
    "playwright": {
      "timeout": 30,
      "wait": 30,
      "install": false,
      "browser": "Chromium"
    }
  }
}

PluginConnectorConfig

コネクタはプラグインシステムを介して定義できます。これを使用するには、Fitter/Cli(プラグインの場所)に次のフラグを適用する必要があります:

... --plugins=./examples/plugin

--plugins - 指定されたフォルダ内の ".so" 拡張子を持つすべてのファイルを検索します(サブディレクトリは除外)

type PluginConnectorConfig struct {
	Name   string          `json:"name" yaml:"name"`
	Config json.RawMessage `json:"config" yaml:"config"`
}
{
    "name": "connector",
    "config": {
      "name": "Elon"
    }
}
  • Name - プラグインの名前

  • Config - プラグインの json 設定

プラグインのビルド方法

プラグインをビルドします

go build -buildmode=plugin -gcflags="all=-N -l" -o examples/plugin/connector.so examples/plugin/connector/connector.go

pl.ConnectorPlugin インターフェースを実装する Plugin 変数をエクスポートしてください

CLI の例:

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_plugin.json#L5

プラグインの例:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/PxyUp/fitter/pkg/config"
	"github.com/PxyUp/fitter/pkg/logger"
	"github.com/PxyUp/fitter/pkg/builder"
	pl "github.com/PxyUp/fitter/pkg/plugins/plugin"
)

var (
	_ pl.ConnectorPlugin = &plugin{}

	Plugin plugin
)

type plugin struct {
	log  logger.Logger
	Name string `json:"name" yaml:"name"`
}

func (pl *plugin) Get(ctx context.Context, parsedValue builder.Interfacable, index *uint32, input builder.Interfacable) ([]byte, error) {
	return []byte(fmt.Sprintf(`{"name": "%s"}`, pl.Name)), nil
}

func (pl *plugin) SetConfig(cfg *config.PluginConnectorConfig, logger logger.Logger) {
	pl.log = logger

	if cfg.Config != nil {
		err := json.Unmarshal(cfg.Config, pl)
		if err != nil {
			pl.log.Errorw("cant unmarshal plugin configuration", "error", err.Error())
			return
		}
	}
}

ReferenceConnectorConfig

references からプリフェッチされたデータを取得できるコネクタ

type ReferenceConnectorConfig struct {
	Name string `yaml:"name" json:"name"`
}

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_ref.json#L66

IntSequenceConnectorConfig

結果として整数シーケンスを生成する静的コネクタの改良版

type IntSequenceConnectorConfig struct {
	Start int `json:"start" yaml:"start"`
	End   int `json:"end" yaml:"end"`
	Step  int `json:"step" yaml:"step"`
}
  • Start[0] - 生成の開始点(含む)

  • End[0] - 生成の終了点(任意の言語の range と同様に最終結果から除外)

  • Step[1] - シーケンスの間隔

{
    "start": 0,
    "end": 2 
    // Generate [0, 1]
}

設定例

FileConnectorConfig

指定されたファイルからデータを取得するコネクタタイプ

type FileConnectorConfig struct {
    Path          string `yaml:"path" json:"path"`
    UseFormatting bool   `yaml:"use_formatting" json:"use_formatting"`
}

StaticConnectorConfig

指定された文字列からデータを取得するコネクタタイプ

type StaticConnectorConfig struct {
    Value string `json:"value" yaml:"value"`
    Raw   json.RawMessage `json:"raw" yaml:"raw"`
}
  • Value - データとしての静的文字列。html、json にすることができます

  • Raw - 生の json を受け入れます。フォーマット もサポート

例:

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_static_connector.json#L5

{
  "value": "[1,2,3,4,5]"
}

ServerConnectorConfig

golang の http.Client(curl のようなサーバーサイドリクエスト)を使用してデータを取得するコネクタタイプ

type ServerConnectorConfig struct {
    Method        string            `json:"method" yaml:"method"`
    Headers       map[string]string `yaml:"headers" json:"headers"`
    Timeout       uint32            `yaml:"timeout" json:"timeout"`
    JsonRawBody   json.RawMessage   `json:"json_raw_body" yaml:"json_raw_body"`
    Body          string            `yaml:"body" json:"body"`
    ErrorOnStatus bool              `json:"error_on_status" yaml:"error_on_status"`
    
    Proxy  *ProxyConfig  `yaml:"proxy" json:"proxy"`
    OAuth2 *OAuth2Config `yaml:"oauth2" json:"oauth2"`
}
  • Method - すべての HTTP メソッドをサポート: GET、POST、PUT、DELETE、PATCH、OPTIONS、HEAD

  • Headers - リクエスト中に使用する事前定義ヘッダー。キー/値に注入可能

  • Timeout[sec] - デフォルトは 60 秒のタイムアウト、または指定された値を使用

  • Body - リクエストのボディ。解析された値は注入可能

  • JsonRawBody - json 形式のリクエストボディ。値は注入可能

  • ErrorOnStatus - オプション、デフォルトは falsetrue の場合、HTTP レスポンスステータス >= 400 はエラーボディの解析ではなくフェッチエラー(attempts / null_on_error を通過)として扱われるため、フェッチの失敗と本当に空の結果を区別できます。false のままにすると、返ってきたボディを解析する元の動作が維持されます。

  • Proxy - リクエストのプロキシを設定 設定

  • OAuth2 - アクセストークンを自動的に取得/更新し、Authorization ヘッダーとして送信します 設定

リクエストはデフォルトで識別可能な User-Agent(fitter (+https://github.com/PxyUp/fitter))を送信します。上書きするには Headers で独自の User-Agent を設定してください。

例:

{
  "method": "GET",
  "proxy": {
    "server": "http://localhost:8080",
    "username": "pyx"
  }
}
OAuth2 設定

リクエストの前にアクセストークンを自動的に取得し、Authorization ヘッダーとして注入します(headers で設定されたものを上書き)。トークンはメモリにキャッシュされ、有効期限前に更新されます。401 レスポンスが返された場合、キャッシュされたトークンは破棄され、新しいトークンでリクエストが 1 回再試行されます。

type OAuth2Config struct {
    TokenUrl       string            `json:"token_url" yaml:"token_url"`
    GrantType      OAuth2GrantType   `json:"grant_type" yaml:"grant_type"`
    ClientId       string            `json:"client_id" yaml:"client_id"`
    ClientSecret   string            `json:"client_secret" yaml:"client_secret"`
    Scopes         []string          `json:"scopes" yaml:"scopes"`
    RefreshToken   string            `json:"refresh_token" yaml:"refresh_token"`
    EndpointParams map[string]string `json:"endpoint_params" yaml:"endpoint_params"`
    AuthStyle      string            `json:"auth_style" yaml:"auth_style"`
    TokenFile      string            `json:"token_file" yaml:"token_file"`
}
  • TokenUrl - トークンエンドポイントの URL。フォーマット もサポート

  • GrantType - enum["client_credentials", "refresh_token"]、デフォルトは "client_credentials"。ユーザーが一度同意した API(Google、Microsoft など)で長期有効なリフレッシュトークンを保持している場合は "refresh_token" を使用します

  • ClientId/ClientSecret - クライアント認証情報。フォーマット もサポート。例: {{{FromEnv=CLIENT_SECRET}}}

  • Scopes - 要求するスコープ

  • RefreshToken - "refresh_token" グラントに必要。フォーマット もサポート

  • EndpointParams - 追加のトークンエンドポイントパラメータ(例: Auth0 の audience)。"client_credentials" グラントのみ

  • AuthStyle - enum["", "header", "params"] - クライアント認証情報をトークンエンドポイントに渡す方法: basic auth ヘッダーまたはリクエストボディ。空の場合は自動検出

  • TokenFile - 実行間でトークンを永続化するためのオプションのパス(~/ をサポート)。保存されたトークンは RefreshToken より優先され、ローテーションされたリフレッシュトークンが書き戻されます。単回使用のリフレッシュトークンを提供するプロバイダー(GitHub Apps など)に必要です。fitter_cli auth で作成します

例:

{
  "method": "GET",
  "oauth2": {
    "token_url": "https://oauth2.googleapis.com/token",
    "grant_type": "refresh_token",
    "client_id": "{{{FromEnv=GOOGLE_CLIENT_ID}}}",
    "client_secret": "{{{FromEnv=GOOGLE_CLIENT_SECRET}}}",
    "refresh_token": "{{{FromEnv=GOOGLE_REFRESH_TOKEN}}}"
  }
}
プロキシ設定
type ProxyConfig struct {
    // Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example
    // `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128`
    // is considered an HTTP proxy.
    Server string `json:"server" yaml:"server"`
    // Optional username to use if HTTP proxy requires authentication.
    Username string `json:"username" yaml:"username"`
    // Optional password to use if HTTP proxy requires authentication.
    Password string `json:"password" yaml:"password"`
}
  • Server - プロキシサーバーのスキーマ付きアドレス。フォーマット もサポート

  • Username - プロキシのユーザー名(空にできます)。フォーマット もサポート

  • Password - プロキシのパスワード(空にできます)。フォーマット もサポート

{
  "server": "http://localhost:8080",
  "username": "pyx"
}
環境変数
  1. FITTER_HTTP_WORKER - int[1000] - デフォルトの同時 HTTP ワーカー数

BrowserConnectorConfig

ブラウザを介したデータ取得をエミュレートするコネクタタイプ

type BrowserConnectorConfig struct {
	Chromium   *ChromiumConfig   `json:"chromium" yaml:"chromium"`
	Docker     *DockerConfig     `json:"docker" yaml:"docker"`
	Playwright *PlaywrightConfig `json:"playwright" yaml:"playwright"`
}

設定は次のいずれかになります:

  • Chromium - ローカルにインストールされた Chromium を使用してデータを取得

  • Docker - データ取得用のコンテナを起動するサービスとして docker を使用

  • Playwright - データ取得に playwright フレームワークを使用

例:

{
    "docker": {
      "wait": 10000,
      "image": "docker.io/zenika/alpine-chrome:with-node",
      "entry_point": "chromium-browser",
      "purge": true
    }
}

Chromium

ローカルにインストールされた Chromium を使用してデータを取得します

type ChromiumConfig struct {
	Path    string   `yaml:"path" json:"path"`
	Timeout uint32   `yaml:"timeout" json:"timeout"`
	Wait    uint32   `yaml:"wait" json:"wait"`
	Flags   []string `yaml:"flags" json:"flags"`
}
  • Path - Chromium バイナリへのパス

  • Timeout[sec] - chromium の実行タイムアウト

  • Wait[msec] - ページ読み込みのタイムアウト

  • Flags - Chromium のフラグ。デフォルト: "--headless", "--proxy-auto-detect", "--temp-profile", "--incognito", "--disable-logging", "--disable-extensions", "--no-sandbox"

例:

{
  "path": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
  "wait": 10000
}

Docker

データ取得用のコンテナを起動するために Docker を使用します

type DockerConfig struct {
	Image       string   `yaml:"image" json:"image"`
	EntryPoint  string   `json:"entry_point" yaml:"entry_point"`
	Timeout     uint32   `yaml:"timeout" json:"timeout"`
	Wait        uint32   `yaml:"wait" json:"wait"`
	Flags       []string `yaml:"flags" json:"flags"`
	Purge       bool     `json:"purge" yaml:"purge"`
	NoPull      bool     `yaml:"no_pull" json:"no_pull"`
	PullTimeout uint32   `yaml:"pull_timeout" json:"pull_timeout"`
}

Docker デフォルトイメージ: docker.io/zenika/alpine-chrome

  • Image - docker レジストリのイメージ(レジストリホスト付きで指定)

  • EntryPoint - コンテナ内で実行されるコマンド

  • Timeout[sec] - コンテナ実行のタイムアウト(イメージのプルは含まない)

  • Wait[msec] - ページ読み込みのタイムアウト(Chromium ベースのコンテナのみで機能)

  • Flags - コンテナ実行のコマンド引数。Chromium ベースのデフォルト: "--no-sandbox","--headless", "--proxy-auto-detect", "--temp-profile", "--incognito", "--disable-logging", "--disable-gpu"

  • Purge - 作業完了後にコンテナを削除するかどうか(docker rm と同様)

  • NoPull - イメージのプルを防止

  • PullTimeout - コンテナのプルのタイムアウトを定義

環境変数
  1. DOCKER_HOST - string - (EnvOverrideHost) docker サーバーの URL を設定します。

  2. DOCKER_API_VERSION - string - (EnvOverrideAPIVersion) 使用する API のバージョンを設定します。最新の場合は空のままにします。

  3. DOCKER_CERT_PATH - string - (EnvOverrideCertPath) TLS 証明書(ca.pem、cert.pem、key.pem)を読み込むディレクトリを指定します。

  4. DOCKER_TLS_VERIFY - bool - (EnvTLSVerify) TLS 検証を有効または無効にします(デフォルトはオフ)

例:

{
  "wait": 10000,
  "image": "docker.io/zenika/alpine-chrome:with-node",
  "entry_point": "chromium-browser",
  "purge": true
}

Playwright

playwright フレームワークを介してブラウザを実行します

type PlaywrightConfig struct {
    Browser       PlaywrightBrowser          `json:"browser" yaml:"browser"`
    Install       bool                       `yaml:"install" json:"install"`
    Timeout       uint32                     `yaml:"timeout" json:"timeout"`
    Wait          uint32                     `yaml:"wait" json:"wait"`
    TypeOfWait    *playwright.WaitUntilState `json:"type_of_wait" yaml:"type_of_wait"`
    PreRunScript  string                     `json:"pre_run_script" yaml:"pre_run_script"`
    PostRunScript string                     `json:"post_run_script" yaml:"post_run_script"`
    Stealth       bool                       `json:"stealth" yaml:"stealth"`
    
    StorageStateFile string `json:"storage_state_file" yaml:"storage_state_file"`
    IndexedDB        bool   `json:"indexed_db" yaml:"indexed_db"`
    
    Proxy *ProxyConfig `yaml:"proxy" json:"proxy"`
}
  • Browser - enum["Chromium", "FireFox", "WebKit"] - 使用するブラウザ

  • Install - ブラウザをインストールするかどうか(初回使用時に組み込みの playwright-go バージョンに一致するドライバーとブラウザをダウンロードします。これらがプリインストールされている ghcr.io/pxyup/fitter-mcp:playwright イメージでは不要)

  • Timeout[sec] - playwright を実行するタイムアウト

  • Wait[sec] - ページ読み込みのタイムアウト

  • TypeOfWait - enum["load", "domcontentloaded", "networkidle", "commit"] 待機するページの状態。デフォルトは "load"

  • PreRunScript[""] - AddInitScript を介して注入され、ページスクリプトが実行される前に実行されるスクリプト(ドキュメント作成時、ナビゲーション完了前)。環境のパッチ適用(navigator のオーバーライド、API スタブ)に役立ちます。読み込まれた DOM にはアクセスできません。プレースホルダー {PL} もサポート

  • PostRunScript[""] - ページ読み込み後、ページコンテンツの読み取り前に実行されるスクリプト。DOM 操作(クリック、スクロール)に役立ちます。プレースホルダー {PL} もサポート

  • Stealth[false] - ボット防御を通過するためのスクリプトを追加

  • StorageStateFile[""] - playwright のストレージ状態 json(cookie + localStorage)へのパス(~/ をサポート)。ナビゲーション前にブラウザコンテキストに読み込まれ、毎回の実行後に書き戻されるため、更新されたセッションが維持されます。ヘッドレス実行で実際のログインを再利用できます。fitter_cli browser-login でファイルを一度作成します。ログインとスクレイピングには同じ browser を使用してください。サイトがセッションをブラウザのフィンガープリントにバインドする場合があります。フォーマット もサポート

  • IndexedDB[false] - 永続化されたストレージ状態に IndexedDB を含めます(一部の SPA、例: Firebase Auth はトークンをそこに保持します)

  • Proxy - リクエストのプロキシを設定 設定

{
  "timeout": 30,
  "wait": 30,
  "install": false,
  "browser": "Chromium"
}

Related MCP server: MCP Server Fetch Python

Model

モデルを使用してスクレイピングの結果を定義します

type Model struct {
    ObjectConfig *ObjectConfig `yaml:"object_config" json:"object_config"`
    ArrayConfig  *ArrayConfig  `json:"array_config" yaml:"array_config"`
    BaseField    *BaseField    `json:"base_field" yaml:"base_field"`
    IsArray      bool          `json:"is_array" yaml:"is_array"`
}

設定は次のいずれかになります:

  • ObjectConfig - オブジェクト形式の設定

  • ArrayConfig - 配列形式の設定

  • BaseField - 単一/生成フィールドの設定

  • IsArray - bool[false] - フィールドが配列であることを強制指定します(model fieldbase field の組み合わせで使用可能)

例:

{
  "object_config": {}
}

ObjectConfig

オブジェクトとフィールドの設定

type ObjectConfig struct {
    Fields      map[string]*Field `json:"fields" yaml:"fields"`
    Field       *BaseField        `json:"field" yaml:"field"`
    ArrayConfig *ArrayConfig      `json:"array_config" yaml:"array_config"`

    Condition string `json:"condition" yaml:"condition"`
}
  • Condition - オプションの条件式。解決にソースノードに対して評価されます。false の場合、オブジェクト全体が親から省略されます(フィールドは一切解決されません)

設定は次のいずれかになります:

  • Fields - 各フィールド定義のマップ。キー - フィールド名、値 - 設定

  • Field - 配列の要素に使用。 "string"、"int" などの基本型としてデシリアライズされるフィールド(基本型の配列の場合に使用)

  • ArrayConfig - 配列の要素に使用。配列の配列のデシリアライズ

例:

{
  "fields": {
    "title": {
      "base_field": {
        "type": "string",
        "path": "type"
      }
    }
  }
}

ArrayConfig

配列とフィールドの設定

type ArrayConfig struct {
    RootPath    string        `json:"root_path" yaml:"root_path"`
    Reverse     bool          `yaml:"reverse" json:"reverse"`
    
    ItemConfig  *ObjectConfig `json:"item_config" yaml:"item_config"`
    LengthLimit uint32        `json:"length_limit" yaml:"length_limit"`

    Condition     string `json:"condition" yaml:"condition"`
    ItemCondition string `json:"item_condition" yaml:"item_condition"`
    
    StaticConfig *StaticArrayConfig `json:"static_array"  yaml:"static_array"`
}
  • RootPath - html 解析の場合に配列のルート要素または繰り返し要素を見つけるためのセレクター。配列のサイズはルートの下の子要素の数になります

  • Reverse - bool[false] - 逆順の反復(n から 1)を使用する必要があることを示します

  • LengthLimit - 配列の固定サイズ(生成された配列のみ。静的には使用不可)。注: ソースの要素が制限より少ない場合、宣言されたサイズを維持するために配列は末尾に nullパディングされます(これは意図的です)— 代わりにソースの正確な長さを得るには length_limit を省略してください

  • Condition - オプションの条件式。解決にソースノードに対して評価されます。false の場合、配列全体が親から省略されます

  • ItemCondition - オプションの条件式。すべての構築済みアイテムに対して評価されます(fRes - アイテム値、fSrc - ソース要素、fIndex - アイテムインデックス)。false に解決されるアイテムは配列から削除されます - 宣言的フィルタリング。static_array には適用されません

設定は次のいずれかになります:

例:

{
  "root_path": "#content dt.quote > a",
  "item_config": {
    "field": {
      "type": "string"
    }
  }
}

Field

フィールドの共通部分

type Field struct {
	BaseField    *BaseField    `json:"base_field" yaml:"base_field"`
	ObjectConfig *ObjectConfig `json:"object_config" yaml:"object_config"`
	ArrayConfig  *ArrayConfig  `json:"array_config" yaml:"array_config"`

	FirstOf []*Field `json:"first_of" yaml:"first_of"`
}

設定は以下のいずれかになります:

  • BaseField - "string"、"int" などの基本型のようにデシリアライズされるフィールド

  • ObjectConfig - フィールドがネストされたオブジェクト内にある場合

  • ArrayConfig - フィールドが配列内にある場合

  • FirstOf - 最初に空でない解決済みフィールドが選択されます

例:

{
  "base_field": {
    "type": "string",
    "path": "div.current-temp span.heading"
  }
}

BaseField

静的な情報を取得したり、新しい情報を生成したい場合

type BaseField struct {
	Type FieldType `yaml:"type" json:"type"`
	Path string    `yaml:"path" json:"path"`

	HTMLAttribute string `json:"html_attribute" yaml:"html_attribute"`

	Condition string `json:"condition" yaml:"condition"`

	Generated *GeneratedFieldConfig `yaml:"generated" json:"generated"`

	FirstOf []*BaseField `json:"first_of" yaml:"first_of"`
}
  • FieldType - enum["null", "boolean", "string", "int", "int64", "float", "float64", "array", "object", "html", "raw_string"] - パース用の静的フィールド。重要: html 型は HTML を返すコネクタでのみ動作します(この場合 HTMLAttribute は効果がありません)。

  • Path - パース用のセレクタ(配列の子の場合は相対指定)

  • HTMLAttribute - goquery による HTML パースでのみ効果がある追加値。ここでパースする属性を指定できます。

  • Condition - 任意の condition 式。抽出された値(fRes/fResJson/fResRaw、fIndex; fSrc - フィールドが解決されたノード(兄弟要素を含む))に対して評価されます。false の場合、フィールドは null を生成する代わりに親オブジェクト/配列から省略されます。Generated の前に評価されるため、条件が false の場合、生成処理(サブリクエスト、ファイルダウンロード)もスキップされます。

重要: デフォルトでは "string" 型はトリムされ、すべての特殊文字が置換されます。プレーンな文字列が必要な場合は "raw_string" を使用してください。

設定は以下のいずれか、または空にできます:

  • Generated - カスタム設定で生成できるフィールド

  • FirstOf - 最初に空でない解決済みフィールドが選択されます

{
  "generated": {
    "uuid": {}
  }
}
{
  "type": "string",
  "path": "text()"
}

条件付きフィールド

すべてのフィールドは condition を持つことができます - expr-lang 式(定義済み値)。true 以外の値に評価された場合、フィールドは出力から省略されます(キー/アイテムが消えます)。null には設定されません。無効な式もフィールドを省略し、エラーをログに記録します。

条件が評価される場所:

  • BaseField.condition - 抽出後: fRes は抽出された値、fSrc はフィールドが解決されたノード(その兄弟要素を含む)です。つまり fSrc.on_sale == true で、抽出していないデータに基づいてフィールドを制御できます。条件が false の場合、generated 処理は完全にスキップされます(サブリクエストなし、ファイルダウンロードなし)

  • ObjectConfig.condition / ArrayConfig.condition - 解決前: fRes/fSrc はソースノードです(json の場合はパースされた値、html の場合はテキストコンテンツ)

  • ArrayConfig.item_condition - 構築された各アイテムに対して: fRes はアイテム、fSrc はそれが構築されたソース要素、fIndex はそのインデックスです。false のアイテムは削除されます - 宣言的な配列フィルタリングです。fSrc を使用して、出力に追加せずにソース属性でフィルタリングできます。

配列アイテムのフィルタリング - fSrc.in_stock はソース要素を読み取り(出力には抽出されません)、fRes.price は構築されたアイテムを読み取ります:

{
  "array_config": {
    "root_path": "products",
    "item_condition": "fSrc.in_stock && fRes.price > 0",
    "item_config": {
      "fields": {
        "title": { "base_field": { "type": "string", "path": "title" } },
        "price": { "base_field": { "type": "float", "path": "price" } }
      }
    }
  }
}

値がチェックに合格しない限りキーを省略:

{
  "discount": {
    "base_field": {
      "type": "float",
      "path": "discount_pct",
      "condition": "fRes > 0"
    }
  }
}

特殊なケース:

  • 静的配列内では、省略されたアイテムは null のままです(位置は定義上固定されており、インデックスは決してシフトしません)

  • ルートモデル設定が省略された場合、パース結果は null になります

  • first_of 内では、条件が false のブランチは空としてカウントされるため、次のブランチが試行されます

実行可能な例: examples/config_conditions.json

GeneratedFieldConfig

フィールドをその場で生成する機能を提供します

type GeneratedFieldConfig struct {
    UUID             *UUIDGeneratedFieldConfig   `yaml:"uuid" json:"uuid"`
    Static           *StaticGeneratedFieldConfig `yaml:"static" json:"static"`
    Formatted        *FormattedFieldConfig       `json:"formatted" yaml:"formatted"`
    Plugin           *PluginFieldConfig          `yaml:"plugin" json:"plugin"`
    Calculated       *CalculatedConfig           `yaml:"calculated" json:"calculated"`
    File             *FileFieldConfig            `yaml:"file" json:"file"`
    Model            *ModelField                 `yaml:"model" json:"model"`
    FileStorageField *FileStorageField           `json:"file_storage" yaml:"file_storage"`
}

設定は以下のいずれかになります:

  • UUID - ランダムな UUID V4 を生成

  • Static - 静的フィールドを生成

  • Formatted - フィールドをフォーマット

  • Model - 他のコネクタとモデルから生成されたモデル

  • Plugin - プラグインフィールド

  • Calculated - 計算フィールド

  • File - ファイルフィールド(サーバーからファイルをダウンロードするため)

  • FileStorage - ローカルファイルに保存できるファイルフィールド

例:

{
    "uuid": {}
}

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_cli.json#L58

{
    "model": {
      "type": "array",
      "model": {
        "array_config": {
          "root_path": "#content dt.quote > a",
          "item_config": {
            "field": {
              "type": "string"
            }
          }
        }
      },
      "connector_config": {
        "response_type": "HTML",
        "url": "http://www.quotationspage.com/random.php",
        "attempts": 3,
        "browser_config": {
          "chromium": {
            "path": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
            "wait": 10000
          }
        }
      }
    }
}

UUID

その場でランダムな UUID V4 を生成します。一意の ID を生成するために使用できます。

type UUIDGeneratedFieldConfig struct {
	Regexp string `yaml:"regexp" json:"regexp"`
}
  • Regexp - 生成された UUID の一部を取得するために使用できるマッチャーを提供します

Static

静的フィールドを生成します

type StaticGeneratedFieldConfig struct {
    Type  FieldType       `yaml:"type" json:"type"`
    Value string          `json:"value" yaml:"value"`
    Raw   json.RawMessage `json:"raw" yaml:"raw"`
}
  • Type - enum["null", "boolean", "string", "int","int64","float","float64", "array", "object"] - フィールドの型

  • Value - フィールドの文字列値

  • Raw - フィールドの純粋な json 値

{
  "type": "int",
  "value": "65"
}
{
  "type": "array",
  "value": "[65,45]"
}
{
  "type": "array",
  "raw": [65,45]
}

Formatted Field Config

親の base field から値を渡すフォーマット済みフィールドを生成します

type FormattedFieldConfig struct {
	Template string `yaml:"template" json:"template"`
}
  • Template - プレースホルダー {PL} を含むテンプレート。ここに parent の値が文字列として注入されます

例: https://github.com/PxyUp/fitter/blob/master/examples/cli/config_cli.json#L98

{
  "template": "https://news.ycombinator.com/item?id={PL}"
}

File Storage Field

フィールドの結果をローカルファイルとして保存するために使用できるフィールド

type FileStorageField struct {
    Content string          `json:"content" yaml:"content"`
    Raw     json.RawMessage `yaml:"raw" yaml:"raw"`
    
    FileName string `json:"file_name" yaml:"file_name"`
    Path     string `json:"path" yaml:"path"`
    Append   bool   `json:"append" yaml:"append"`
}
  • Content - コンテンツ用のテンプレート文字列。重要: 親の値を文字列として注入できます

  • Raw - フィールドの生の json コンテンツ。重要: 親の値を文字列として注入できます

  • FileName - ファイルを保存するためのローカルファイル名。デフォルトでは、ヘッダーから FileName を取得しようとし、その後 URL から取得します。重要: 親の値を文字列として注入できます。

  • Path - ファイルを保存するためのローカルファイルの親ディレクトリ。デフォルトのパスはプロセスディレクトリです。重要: 親の値を文字列として注入できます

  • Append[false] - ファイルに追記するかどうか

{
  "content": "{{{id}}}, {{{message}}}\n",
  "append": true,
  "file_name": "{{{id}}}.csv",
  "path": "/Users/pxyup/fitter/examples/cli/test/csv"
}

File Field

サーバーからファイルをローカルにダウンロードするために使用できるフィールド

type FileFieldConfig struct {
	Config *ServerConnectorConfig `yaml:"config" json:"config"`

	Url      string `yaml:"url" json:"url"`
	FileName string `json:"file_name" yaml:"file_name"`
	Path     string `json:"path" yaml:"path"`
}
  • Config - ServerConfig はデフォルトの fitter http.Client を使用してリクエストを送信します

  • Url - 画像の URL。重要: コネクタ内の URL は 親の値を文字列として注入できます

  • FileName - ファイルを保存するためのローカルファイル名。デフォルトでは、ヘッダーから FileName を取得しようとし、その後 URL から取得します。重要: 親の値を文字列として注入できます。

  • Path - ファイルを保存するためのローカルファイルの親ディレクトリ。デフォルトのパスはプロセスディレクトリです。重要: 親の値を文字列として注入できます

フィールドの結果は、ローカルファイルパスが文字列として返されます

{
  "url": "https://images.shcdn.de/resized/w680/p/dekostoff-gobelinstoff-panel-oriental-cat-46-x-46_P19-KP_2.jpg",
  "path": "/Users/pxyup/fitter/bin",
  "config": {
    "method": "GET"
  }
}

伝播された URL を使用(親の値を文字列として注入

{
  "url": "https://picsum.photos{PL}",
  "path": "/Users/pxyup/fitter/bin",
  "config": {
    "method": "GET"
  }
}

設定例:

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_image.json

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_image_multiple.json

Calculated field

式に応じて異なる型を生成できるフィールド

type CalculatedConfig struct {
	Type       FieldType `yaml:"type" json:"type"`
	Expression string    `yaml:"expression" json:"expression"`
}
  • Type - 式の結果の型

  • Expression - 計算用の式(計算式には このライブラリ を使用します)

定義済み値

FNull - builder.Nullvalue のエイリアス

FNil - nil のエイリアス

isNull(value T) - 値が FNull かどうかをチェックする関数

fRes - base field のパース結果の生の(適切な型の)値

fIndex - 親配列内のインデックス(親が配列フィールドの場合のみ)

fResJson - 生の結果の JSON 文字列表現

fResRaw - バイト形式の結果

fSrc - condition/item_condition 式でのみ使用可能: 値が解決されたソースノード(json の場合はパースされた値(兄弟要素を含む)、html の場合はテキストコンテンツ)。calculated/formatted/notifier 式では使用できません

FNewLine - 改行区切り文字

{
  "type": "bool",
  "expression": "fRes > 500"
}

Plugin field

fitter 用の外部プラグインにできるフィールド

詳細

type PluginFieldConfig struct {
	Name string `json:"name" yaml:"name"`
	Config json.RawMessage `json:"config" yaml:"config"`
}
  • Name - プラグインの名前(拡張子なしの名前のみ)

  • Config - プラグインの json 設定

Model Field

新しい modelconnector によってその場で生成できるフィールド型

type ModelField struct {
	// Type of parsing
	ConnectorConfig *ConnectorConfig `yaml:"connector_config" json:"connector_config"`
	// Model of the response
	Model *Model `yaml:"model" json:"model"`

	Type FieldType `yaml:"type" json:"type"`
	Path string             `yaml:"path" json:"path"`

	Expression string    `yaml:"expression" json:"expression"`
}
  • ConnectorConfig - 使用するコネクタ。重要: コネクタ内の URL は 親の値を文字列として注入できます

  • Model - 内部モデルの設定

  • Type - enum["null", "boolean", "string", "int", "int64", "float", "float64", "array", "object"] - 生成されたフィールドの型

  • Path - 生成されたフィールドから情報を抽出できない場合に、json セレクタを使用して抽出できます

  • Expression - Model の後処理に使用できる文字列(path フィールドは無視されます

例:

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_cli.json#L60

{
  "type": "array",
  "model": {
    "array_config": {
      "root_path": "#content dt.quote > a",
      "item_config": {
        "field": {
          "type": "string"
        }
      }
    }
  }
}

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_weather.json#L37

{
    "type": "string",
    "path": "temp.temp",
    "model": {
       "object_config": {
        "fields": {
          "temp": {
            "base_field": {
              "type": "string",
              "path": "//div[@id='forecast_list_ul']//td/b/a/@href",
              "generated": {
                "model": {
                  "type": "string",
                  "model": {
                    "object_config": {
                      "fields": {
                        "temp": {
                          "base_field": {
                            "type": "string",
                            "path": "div.current-temp span.heading"
                          }
                        }
                      }
                    }
                  },
                  "connector_config": {
                    "response_type": "HTML",
                    "attempts": 4,
                    "url": "https://openweathermap.org{PL}",
                    "browser_config": {
                      "playwright": {
                        "timeout": 30,
                        "wait": 30,
                        "install": false,
                        "browser": "FireFox",
                        "type_of_wait": "networkidle"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "connector_config": {
      "response_type": "xpath",
      "attempts": 3,
      "url": "https://openweathermap.org/find?q={PL}",
      "browser_config": {
        "playwright": {
          "timeout": 30,
          "wait": 30,
          "install": false,
          "browser": "Chromium"
        }
      }
    }
}

Static Array Config

静的(固定長)配列の生成を提供します

type StaticArrayConfig struct {
    Items map[uint32]*Field `yaml:"items" json:"items"`
    Length uint32            `yaml:"length" json:"length"`
}
  • Items - map[uint32]*Field - キーは配列内のインデックス、値はフィールド定義

  • Length - 設定した場合(1以上)、配列のカスタム長を定義するために使用できます

例:

{
  "0": {
    "base_field": {
      "type": "string",
      "path": "div.current-temp span.heading"
    }
  }
}
{
  "length": 4,
  "0": {
    "base_field": {
      "type": "string",
      "path": "div.current-temp span.heading"
    }
  }
}
{
  "length": 4,
  "2": {
    "base_field": {
      "type": "string",
      "path": "div.current-temp span.heading"
    }
  }
}

プレースホルダーリスト

  1. {PL} - 値の注入用

  2. {INDEX} - 親配列内のインデックスの注入用

  3. {HUMAN_INDEX} - 親配列内のインデックスを人間向けの方法で注入するため

  4. {{{json_path}}} - 伝播された "object"/"array" フィールドから情報を取得します

  5. {{{RefName=SomeName}}} - 名前で reference 値を取得します。

  6. {{{RefName=SomeName json.path}}} - 名前で reference 値を取得し、json パスで値を抽出します。

  7. {{{FromEnv=ENV_KEY}}} - 環境変数から値を取得します

  8. {{{FromExp=fRes + 5 + fIndex}}} - から値を取得します。定義済み値

  9. {{{FromInput=.}}} または {{{FromInput=json.path}}} - トリガーまたはライブラリの入力から値を取得します

  10. {{{FromFile=./test_file.log}}} - パスでファイルから値を取得します。ファイルのコンテンツにもプレースホルダーを含めることができます

  11. {{{FromURL=http://localhost:8081}}} - URL からレスポンスを取得します

例:

{{{FromExp="{{{FromEnv=TEST_VAL}}}" + "hello"}}}
Current time is: {PL} with token from TokenRef={{{RefName=TokenRef}}} and TokenObjectRef={{{RefName=TokenObjectRef token}}}
Current time is: {PL} with token from TokenRef={{{RefName=TokenRef}}} and TokenObjectRef={{{RefName=TokenObjectRef token}}}
TokenRef={{{RefName=TokenRef}}} and TokenObjectRef={{{RefName=TokenObjectRef token}}} Object={{{value}}} {PL} Env={{{FromEnv=TEST_VAL}}} {INDEX} {HUMAN_INDEX}

References

事前取得される(処理前に)特別なマップで、connector または placeholder に使用できます。

以下の用途に使用できます:

  1. jwt トークンをキャッシュしてヘッダーで使用

  2. 値のキャッシュ

  3. など

Reference

type Reference struct {
    *ModelField
    
    Expire *uint32 `yaml:"expire" json:"expire"`
}
  • ModelField - 埋め込み構造体です。同じフィールドを使用できます

  • Expire[sec] - 取得後に参照が期限切れになる期間。未設定 => 永久にキャッシュ。0 に設定 => 毎回再取得。n > 0 に設定 => n 秒間キャッシュ

Fitter の場合

type RefMap map[string]*Reference

type Config struct {
    // Other Config Fields

    Limits     *Limits `yaml:"limits" json:"limits"`
    References RefMap  `json:"references" yaml:"references"`
}

Fitter Cli の場合

type RefMap map[string]*Reference

type CliItem struct {
    // Other Config Fields

    Limits     *Limits `yaml:"limits" json:"limits"`
    References RefMap  `json:"references" yaml:"references"`
}

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_ref.json#L2

{
  "references": {
    "TokenRef": {
      "expire": 10,
      "connector_config": {
        "response_type": "json",
        "static_config": {
          "value": "\"plain token\""
        }
      },
      "model": {
        "base_field": {
          "type": "string"
        }
      }
    },
    "TokenObjectRef": {
      "connector_config": {
        "response_type": "json",
        "static_config": {
          "value": "{\"token\":\"token from object\"}"
        }
      },
      "model": {
        "object_config": {
          "fields": {
            "token": {
              "base_field": {
                "type": "string",
                "path": "token"
              }
            }
          }
        }
      }
    }
  }
}

Notifiers

任意のアイテムごとの設定 item.notifier_config。処理後にパース結果をどこかにプッシュします。結果は通常どおり返されます(CLI/MCP 出力、サービスログ)。notifier は追加で配信します。Fitter(サービスモード)、Fitter_CLI、Fitter_MCP で動作します。

type NotifierConfig struct {
    Expression      string `yaml:"expression" json:"expression"`
    Force           bool   `json:"force" yaml:"force"`
    SendArrayByItem bool   `yaml:"send_array_by_item" json:"send_array_by_item"`
    Template        string `yaml:"template" json:"template"`

    // exactly ONE destination:
    Console     *ConsoleConfig       `yaml:"console" json:"console"`
    TelegramBot *TelegramBotConfig   `yaml:"telegram_bot" json:"telegram_bot"`
    Http        *HttpConfig          `yaml:"http" json:"http"`
    Redis       *RedisNotifierConfig `json:"redis" yaml:"redis"`
    File        *FileStorageField    `json:"file" yaml:"file"`
}
  • Expression - オプションの expr-lang 条件: それが true と評価された場合のみ通知します。解析結果は fRes (解析値)、fResRaw (生バイト)、fResJson (JSON文字列) として利用できます。例: len(fResRaw) > 0

  • Force - 解析がエラーで終了した場合でも通知します

  • SendArrayByItem - 結果が配列の場合、各要素を個別の通知として送信します

  • Template - 送信前に結果に適用されるオプションのテンプレート。placeholders を使用できます

  • Destination - console, telegram_bot, http, redis, file のいずれか1つ

宛先設定:

type HttpConfig struct {
    Url     string            `yaml:"url" json:"url"`
    Method  string            `json:"method" yaml:"method"`
    Headers map[string]string `yaml:"headers" json:"headers"`
    Timeout uint32            `yaml:"timeout" json:"timeout"`
}

type TelegramBotConfig struct {
    Token   string  `json:"token" yaml:"token"`
    UsersId []int64 `json:"users_id" yaml:"users_id"`
    Pretty  bool    `json:"pretty" yaml:"pretty"`
    OnlyMsg bool    `json:"only_msg" yaml:"only_msg"`
}

type RedisNotifierConfig struct {
    Addr     string `json:"addr" yaml:"addr"`
    Password string `json:"password" yaml:"password"`
    DB       int    `json:"db" yaml:"db"`
    Channel  string `json:"channel" yaml:"channel"`
}

type ConsoleConfig struct {
    OnlyResult bool `json:"only_result" yaml:"only_result"`
}

file 宛先は、ファイルフィールドタイプと同じ FileStorageField を使用します。

例 (examples/config_telegram.json):

{
  "item": {
    "connector_config": { "...": "..." },
    "model": { "...": "..." },
    "notifier_config": {
      "expression": "len(fResRaw) > 0",
      "telegram_bot": {
        "token": "{{{FromEnv=TG_TOKEN}}}",
        "users_id": [123456],
        "pretty": true
      }
    }
  }
}

制限

DDOS攻撃やメモリの大量使用を防ぐための制限を提供します。

type Limits struct {
	HostRequestLimiter HostRequestLimiter `yaml:"host_request_limiter" json:"host_request_limiter"`
	ChromiumInstance   uint32             `yaml:"chromium_instance" json:"chromium_instance"`
	DockerContainers   uint32             `yaml:"docker_containers" json:"docker_containers"`
	PlaywrightInstance uint32             `yaml:"playwright_instance" json:"playwright_instance"`
}
  • HostRequestLimiter - map[string]int64 - ホスト名ごとの制限。キーはホスト、値は並列リクエスト数(server connector で使用)

  • ChromiumInstance - 並列 chromium インスタンスの数

  • DockerContainers - 並列 docker インスタンスの数

  • PlaywrightInstance - 並列 playwright インスタンスの数

https://github.com/PxyUp/fitter/blob/master/examples/cli/config_cli.json#L2

{
  "limits": {
    "host_request_limiter": {
      "hacker-news.firebaseio.com": 5
    },
    "chromium_instance": 3,
    "docker_containers": 3,
    "playwright_instance": 3
  }
}

Available Tools

6 tools
fitter_config_referenceA

Return a condensed reference of the Fitter config format (connectors, parsers, model/field schema, placeholders, notifiers, references, limits) with working examples. Use it before authoring a config for fitter_run.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries burden. Describes output but does not explicitly state that tool is read-only or has no side effects, though context implies safe operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose, no fluff. Every part earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no parameters or output schema, description sufficiently covers purpose and usage. Could mention response format but not critical for a reference tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters, schema coverage is 100% trivially. Baseline 4 applies, and description adds value by listing what the reference includes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it returns a condensed reference of the Fitter config format with working examples, and distinguishes itself from sibling run tools by advising use before authoring a config for fitter_run.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly recommends using before authoring a config for fitter_run, providing clear context. However, it does not mention exclusions or alternatives, but siblings are run tools making differentiation obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fitter_inspect_urlA

Fetch a URL and return a compact structure outline plus candidate selectors/paths, so you can author a fitter config that matches on the first try instead of guessing selectors and getting nulls. For JSON it lists gjson paths with types and sample values; for HTML it lists repeated elements (candidate array_config root_path / list rows) and link/heading selectors. For client-rendered SPAs (content built by JavaScript), a plain fetch sees only an empty shell — the output warns when it detects one; pass render:true to render it in a headless browser first (mirrors what a browser_config scrape would see). Read-only helper that does NOT extract data — use it before fitter_run, then fitter_run to actually extract.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesHTTP(S) URL to fetch and inspect for its structure and candidate selectors.
renderNoRender the page in a headless browser (Playwright/Chromium) before inspecting — needed for client-rendered SPAs whose content is built by JavaScript and is absent from the raw HTML. Requires browser support (the fitter-mcp:playwright image or a local Playwright install).
response_typeNoOptional hint for how to read the response: json, HTML, xpath or XML. Empty auto-detects from the Content-Type/body.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It clearly states the tool is read-only and does not extract data, and explains behavior for different content types (JSON, HTML, SPAs) and the render option.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed but each sentence adds unique value, covering purpose, output, parameter usage, and distinctions from execution tools. It is front-loaded with the primary purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description describes the output as a 'compact structure outline plus candidate selectors/paths' and gives specifics for JSON and HTML. It also covers the render behavior for SPAs, making the tool's behavior well understood.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description expands on each parameter beyond the schema: url as the target, render for SPAs, and response_type as an optional hint with auto-detection. It explains why the parameters matter and how they affect the output.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Fetch a URL and return a compact structure outline') and differentiates from sibling tools by positioning it as an inspection step before fitter_run. Clearly identifies the tool's role.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it ('before fitter_run') and what it does not do ('does NOT extract data'), plus provides guidance on when to set render:true for SPAs. Also mentions the response_type hint.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fitter_runA

Run a Fitter scraping/parsing config passed inline (JSON or YAML) and return the extracted data as JSON. Fitter fetches data via a connector (HTTP request, headless browser, static value, file, ...) and extracts structured data using json/HTML/XML/xpath selectors described by a declarative model. Call fitter_config_reference first if you are unsure about the config format.

ParametersJSON Schema
NameRequiredDescriptionDefault
inputNoOptional input value (plain string or JSON), available in the config via {{{FromInput=.}}} or {{{FromInput=json.path}}} placeholders.
configYesFitter CliItem config as a JSON or YAML string. Top-level keys: item (required), limits, references.

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must disclose behaviors. It mentions fetching data via connectors and extracting data, implying network access. However, it omits potential side effects like rate limits, authentication needs, or error scenarios, which would strengthen transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief, with a clear structure: first sentence states the tool's purpose, second explains the underlying Fitter mechanism, third gives a usage tip. Every sentence contributes directly to understanding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with two parameters, no output schema, and no annotations, the description provides sufficient context: config format, supported selectors, and a reference to the config spec tool. It could be more complete by noting potential timeouts or result size limitations, but overall it covers the essential information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (both parameters described). The description adds context beyond the schema by explaining that config is JSON/YAML, highlighting top-level keys (item, limits, references), and stating that output is JSON. This adds meaningful value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('Run a Fitter scraping/parsing config passed inline') and the resource (inline config). It distinguishes from siblings by specifying 'inline', contrasting with file- and URL-based tools. The purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description advises calling fitter_config_reference first if unsure about the config format, providing clear guidance. However, it does not explicitly compare this tool to fitter_run_file or fitter_run_url, leaving the selection of the appropriate sibling somewhat implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fitter_run_fileA

Run a Fitter scraping/parsing config from a local JSON or YAML file and return the extracted data as JSON. Same as fitter_run but reads the config from disk.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to a Fitter config file (.json, .yaml or .yml) with top-level keys: item (required), limits, references.
inputNoOptional input value (plain string or JSON), available in the config via {{{FromInput=.}}} or {{{FromInput=json.path}}} placeholders.

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description must fully disclose behavioral traits. It states the tool returns extracted data as JSON but does not mention whether modifications occur, required permissions, or error handling (e.g., file not found). The description is minimal and lacks transparency beyond the basic operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with two sentences, front-loading the primary purpose. Every sentence adds value: first defines the tool, second clarifies the difference from a sibling. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 2 parameters and no output schema, the description covers the basic purpose but omits important context like what happens if the file is invalid, permissions needed, or error scenarios. It is adequate for simple use but has gaps compared to a fully transparent description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds minimal additional meaning beyond the schema; it only reiterates that 'input' is optional and used with placeholders, which the schema already covers. No further value is added for the 'path' parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the verb (Run), the resource (Fitter config file), and distinguishes it from fitter_run by specifying 'reads the config from disk.' It also indicates the output format (JSON). This differentiates it from sibling tools like fitter_config_reference, fitter_run, and fitter_run_url.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly notes 'Same as fitter_run but reads the config from disk,' which helps users decide between this tool and fitter_run. However, it does not provide explicit when-not-to-use scenarios or mention other alternatives besides the direct sibling comparison.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fitter_run_urlA

Run a Fitter scraping/parsing config downloaded from an HTTP(S) URL (JSON or YAML) and return the extracted data as JSON. Same as fitter_run but fetches the config from a remote location, e.g. a raw GitHub link.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesHTTP(S) URL of a Fitter config (JSON or YAML) with top-level keys: item (required), limits, references.
inputNoOptional input value (plain string or JSON), available in the config via {{{FromInput=.}}} or {{{FromInput=json.path}}} placeholders.

TDQS

A3.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully disclose behavior. It states the tool downloads config from a URL and returns JSON, but omits important details such as network error handling, timeout limits, authentication, size restrictions, or what happens with invalid configs. This lack of transparency could lead to unexpected failures.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences with no unnecessary words. It front-loads the action and result, then adds the key distinction from 'fitter_run'. Every sentence provides useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool involves remote fetching and parsing, but the description does not detail the return format beyond 'extracted data as JSON', nor does it explain error conditions or required permissions. With no output schema, more detail would be beneficial for an agent to anticipate the response structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already covers both parameters with descriptions (100% coverage). The description adds value by specifying the required top-level keys of the config ('item', 'limits', 'references'), which aids in understanding the expected structure beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool runs a Fitter config from an HTTP(S) URL and returns JSON data. It explicitly distinguishes itself from 'fitter_run' by noting the remote fetching behavior, making the purpose specific and differentiated from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates when to use this tool over 'fitter_run' (remote vs local config) and gives an example (raw GitHub link). However, it does not explicitly mention when not to use it or alternatives like 'fitter_run_file', though the context from the name and sibling list provides some guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fitter_validate_configA

Validate a Fitter config (JSON or YAML) without executing it. Checks the structural rules: item/connector_config/model presence, valid response_type, that the connector has a data source, and compiles every condition/item_condition expression in the model. Returns "valid" or the validation error. Cheap and safe — use it while iterating on a config before calling fitter_run.

ParametersJSON Schema
NameRequiredDescriptionDefault
configYesFitter CliItem config as a JSON or YAML string to validate without executing it.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully carries the burden, detailing what it checks (structural rules, condition compilation), that it is cheap and safe, and that it returns 'valid' or error. This comprehensively discloses behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: purpose, checks, and usage advice. Front-loaded and succinct with no redundancies.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the single parameter and no output schema, the description fully covers purpose, behavior, usage context, and return type. It is complete for effective tool selection.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description reinforces the config parameter but adds no new parameter-level details beyond the schema description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Validate a Fitter config (JSON or YAML) without executing it,' clearly specifying the verb and resource. It distinguishes from sibling tools like fitter_run by advising use before calling fitter_run.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly advises using this tool while iterating on a config before calling fitter_run, providing clear when-to-use context. However, it does not explicitly state when not to use it or mention alternatives for different scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 1 tool updatev1.8.2
    • Addedfitter_inspect_url
  2. 1 tool updatev1.7.0
    • Addedfitter_validate_config
  3. 4 tool updatesv0.1.0
    • First observedfitter_config_reference
    • First observedfitter_run
    • First observedfitter_run_file
    • First observedfitter_run_url

TDQS

A4.4/5.0
Disambiguation5/5

Each tool serves a distinct purpose: reference, inspection, execution (with three source variants), and validation. No overlap or ambiguity between them.

Naming Consistency5/5

All tools follow the 'fitter_' prefix with snake_case, and the action part is consistently descriptive (inspect, run, validate). The naming pattern is uniform and predictable.

Tool Count5/5

Six tools is ideal for a config-driven scraping/parsing workflow: reference, inspect, run (three variants), and validate. Not bloated or sparse.

Completeness5/5

The toolset covers the full lifecycle: learning the format (reference), inspecting target structure (inspect), validating configs (validate), and executing from inline, file, or URL sources. No missing functionality apparent.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

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/PxyUp/fitter'

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