経緯
Clineが良すぎる。
ここまでできたら、外で指示だけ出してコーディングしたい。
具体的に言うと、Github上で Issue を書くと、プルリクができて、プルリク上でAIエージェントとやり取りをして、プルリクを確認しながらコーディングをしたい。
そしたら、スマホの音声入力とかでお外でプログラミングできるじゃん。
作った
Shikigami(式神)というAIエージェントフレームワークを作った。
スマホでつらつらIssueを書いて、GithubActionsにエージェントが飛んでいき、動くのが式神っぽかったので。
音声入力でIssueを書くと、より何か唱えてるっぽくできる。
クラスに @function_calling
という定義をつけると、AIに関数の定義が自動で渡り、AIに自動で関数の定義がわたるようにした。
AIエージェントとしてはよくある形。
ちょうど、ある程度形になったあたりで、OpenAI の AIエージェントフレームワークも出た。
(開発者向けに昨年から公開されていたらしいが私は全く知らなかった。)
OpenAI の AIエージェントフレームワークも、同じように関数にデコレータをつけた関数を、エージェントが呼び出すような感じっぽかった。
OpenAIの方が優れていると思うけどこれはこれでいい経験だし、先にカスタマイズできるのでいいとする。
設計が似てて方針は合ってたんだな、と嬉しくなった。
それはさておき、GithubにIssueを立てると、それを元にプルリクを作り、プルリク上で作業報告をしてくれるAIエージェントができた。
課題はあるものの、コードも生成されている。
たとえば、これで競馬場に行って、参加しなかったレースの間にプログラミングができる。がはは。
API代とMCP対応
できるだけ、トークン数を減らせるようにしたのでClineと同じくらいかちょっと高いくらいの予算でタスクを実行できるものの、やっぱりAPI代が高い。
お金のかからなかったプログラミングに、結構お金がかかるようになってしまった。
そんな折、Claude Desktopを使うと、ローカルのMCPサーバに、リクエストできることを聞いた。
つまり、MCP経由で、月額定額のClaudeに自作エージェントを操作してもらうことができる。渡りに船。
お外では使えないけど、MCP経由でエージェントを操作するのも、それはそれで面白そうだ。
しくみ
つまりこう。
自作エージェントのツール定義
自作AIエージェントの、ツール定義は OpenAIとかと大体同じ。(というか、AIエージェントつくるとこんな感じに大体なる気がする。)
ツールとしてAIが呼び出せる関数に、function_calling
デコレータを設定して、フレームワーク側がそれを整理してAIに「こんな関数群用意したから便利に使って問題を解決してくれでやんす~」と連絡する。
MCPサーバがこれらを呼べるようにする
要するに、自作AIエージェントに渡していた関数定義を、MCPクライアント(Claude Desktop)に渡せるようにすれば良いわけだ。
ただ、MCPのデコレータを自作のAIエージェントのツールにつけて回るのは、なんか違う気がする。
毎回2重で指定が必要になる。
自作のAIエージェント用に収集した関数の定義を、動的にMCPに渡せるようにする。
その詳細については下記に書いた。
つまり、通常、MCPサーバを実装するとなると、下記のように @mcp.tool()
を関数につけて回る必要があるところを、
from typing import Any
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("hidamari_character")
# このデコレータをつけて回るのではなく
@mcp.tool()
async def get_users_favorite_hidamari_schetch_caractor(user_name:str) -> str:
"""get users favorite hidamari schetch caractor
(ユーザー名ごとに、ひだまりスケッチの好きなキャラクターを返す)
Args:
user_name: ユーザー名
"""
if user_name == "masachaco":
return "宮ちゃんです"
return "該当のユーザーの情報は見つかりませんでした"
def main():
# 標準入力で受け付ける
mcp.run(transport='stdio')
if __name__ == "__main__":
# MCPサーバを起動
main()
そうせずに、下記のように書く
from typing import Any
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("hidamari_character")
async def get_users_favorite_hidamari_schetch_caractor(user_name:str) -> str:
"""get users favorite hidamari schetch caractor
(ユーザー名ごとに、ひだまりスケッチの好きなキャラクターを返す)
Args:
user_name: ユーザー名
"""
if user_name == "masachaco":
return "宮ちゃんです"
return "該当のユーザーの情報は見つかりませんでした"
def main():
# デコレータを手動で呼んで、関数を渡すことでも、MCPサーバーに登録できる
mcp.tool()(get_users_favorite_hidamari_schetch_caractor)
mcp.run(transport='stdio')
if __name__ == "__main__":
main()
ことで、自作 AIエージェントように集めていた関数の参照をそのままMCPの呼び出しに流用できる。
なぜなら、自作AIエージェント用の関数定義も、AIが理解できるように関数のコメントがしっかり書かれているので。
implementations = collection_agent_tool() # 自作AIエージェント用に書かれた関数の参照を集める関数
# MCPサーバにツールを登録し
for key in implementations.keys():
mcp.tool()(implementations[key])
# サーバを起動する
mcp.run(transport='stdio')
今回自作AIエージェントに追加した機能はこれだけ。
自作AIエージェント用に書かれた関数の参照を集める関数はすでにあったので、集めた関数の参照をMCPのデコレータに渡すだけ。
5分で終わる。
MCP化した、自作AIエージェントをローカルで動かす
ということで、動的に集めた関数の定義をMCPサーバに渡してみたところ、めちゃくちゃあっさり登録された。
まぁ、もともとAIエージェントように書いていた関数なので、それはそうなんだけど。。。
GithubActionsで自作エージェントに指示したときと同じように、ブログを作らせてみた。
自作AIエージェントは「ワークスペース」の概念を持っていて、そこで作業するので、「ワークスペースにブログを作って欲しいです」とした。
ワークスペースは、ローカルの適当なディレクトリを指している。
ちゃんと、エージェント用のツールを使って作ってくれている。
ごりごりと作業を進めてくれている。
めっちゃ作ってくれる。っていうか止まらない。
AIが効果的に実装を進めるために作った、AIエージェント用ツールをもりもり使ってくれている。
めちゃくちゃいろいろ作って、最後に、作業終了のツールを呼び出してくれた。
出力されたコードを確認する
成果物を確認してみる。
ローカルにファイルがたくさん出力された。素晴らしい。
が、しまった。
pythonで。とか、フレームワークを指定してなかったから。HTMLだけ作っている。
一応ブラウザで見てみる。
でもすごいな。しっかりしてる。
「続きを読む」で続きが表示された。
これなら十中八九、言語やフレームワークも指定すればそれで作ってくれるでしょう。
ブラウザ版、デスクトップ版の、レートのリミットにはすぐ達するだろうけど、待てば回復するし、定額でこれが使えるのはかなり良さそう。
apiだとClaudeの月額料金程度は結構簡単に行ってしまう。
自作のAIエージェントなので、プログラミング以外にも活用できるかも。
というか、こういう動きだと、ツールを作ってるだけで、エージェント自体はMCPクライアントになりますね・・・。
まとめ
自作AIエージェント作りも楽しいし、MCPサーバとして使ってもらうのも楽しい。。。。
何でもできそうな気がする。
関連記事