この記事は前回、および前々回の記事を読んでいることを前提に作られています。
まだ読んでいない方は下のリンクからどうぞ。
まえがき
皆さんどうもこんにちは、ECN技術部所属、Fuseです。
本記事でもまた引き続き、Shin-sibainu氏によって開発されたClaude Code で仮想組織を構築・運営するプラグインcc-companyを拡張していきます。
Claude Codeの弱点として、単体では画像生成ができないというものがあります。
そんな弱点を補うべく、今回は自作MCP1サーバーを使ってOpenAI(gpt-image-2)と連携する「デザイン部署」を作り、秘書に話しかけるだけで画像生成・i2i2編集ができる環境を整えます。

(イメージ図はChatGPTに生成してもらいました)
動作環境
- Claude Code: 2.1.144
- cc-company: 2.1.0
- python 3.12.6
gpt-image-2って?
gpt-image-2は2026年4月に登場した最新の画像生成モデルです。
旧モデルと比較するとコスパも性能も強化されており、かなりおすすめのモデルです。
| モデル名 | 性能・特徴 | テキスト入力コスト (1Mあたり) | 画像出力コスト (1Mあたり) |
|---|---|---|---|
| GPT Image 2 | 最先端モデル。レイアウトの信頼性が高く、画像内のテキスト描画や構造化された実用的な生成に優れる。 | $5.00 (キャッシュ時 $1.25) | $30.00 |
| GPT Image 1.5 | 優れたクリエイティブ性能を持つが、複雑なプロンプトではやや不安定になることがある。 | $5.00 (キャッシュ時 $1.25) | $32.00 |
| GPT Image 1 | 初期の特化型モデル。高品質モードでは高いトークンを消費し、現行モデルより生成コストが高め。 | $5.00 (キャッシュ時 $1.25) | $40.00 |
| 出典:[Pricing | OpenAI API](https://developers.openai.com/api/docs/pricing) |
ディレクトリを作成する
mkdir -p .company/design/projects
でディレクトリを作成し、
touch .company/design/CLAUDE.md
でCLAUDE.mdを作成します。
.company/
└── design/
├── CLAUDE.md
└── projects/
└── [プロジェクト名]/
├── [プロジェクト名].md ← 概要・ステータス管理(秘書が作成)
├── images/ ← 生成した画像
└── prompts/ ← 使用したプロンプトの記録
.company/design/CLAUDE.md を作成します。
# デザイン部署
## 役割
仮デザイン用の画像生成と、生成した画像・プロンプトの管理を担当する。
MCPやAPIを通じて画像生成サービスと連携し、コンセプトアートやサムネイル案を素早く量産する。
## ルール
- プロジェクトごとに `projects/[プロジェクト名]/` フォルダを作成する
- プロジェクト情報・ステータスは `projects/[プロジェクト名]/[プロジェクト名].md` で管理する(秘書が作成)
- 生成画像は `projects/[プロジェクト名]/images/YYYY-MM-DD-[連番].png` で保存(MCPサーバーが自動保存)
- 使用したプロンプトは `projects/[プロジェクト名]/prompts/YYYY-MM-DD.md` に記録する(MCPサーバーが自動記録)
- 仮デザインが採用されたらクリエイティブ部署に引き渡す
## 役割分担
- **MCPサーバー(image-gen)**: 画像生成・保存、プロンプト記録のみ担当
- **秘書**: プロジェクト新規作成時に `[プロジェクト名].md` を作成し、概要・ステータスを管理する
## プロジェクトmdの形式
```markdown
# [プロジェクト名]
## 概要
(目的・用途の説明)
## ステータス
draft / in-progress / delivered
## 生成画像一覧
- YYYY-MM-DD-01.png - (説明)
## 採用画像
- (採用された画像とその理由)
```
## フォルダ構成
- `projects/[プロジェクト名]/[プロジェクト名].md` - プロジェクト情報・ステータス管理
- `projects/[プロジェクト名]/images/` - 生成した画像ファイル
- `projects/[プロジェクト名]/prompts/` - 使用したプロンプトの記録
MCPサーバーを作成する
プロジェクトルートに mcp-servers/image-gen/ フォルダを作り、以下の2ファイルを作成します。
requirements.txt
mcp
openai
server.py
"""
image-gen MCP Server
gpt-image-2 で画像生成・編集(i2i)を行い、.company/design/projects/ に保存する
【ツール一覧】
- generate_image : テキストプロンプトから新規画像を生成
- edit_image : 既存画像をベースにi2i編集(マスク指定も可)
【前提】
- 環境変数 OPENAI_API_KEY にOpenAIのAPIキーを設定すること
- .mcp.json の env セクションで渡すのが簡単(.gitignore 推奨)
"""
import asyncio
import base64
from datetime import date
from pathlib import Path
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import TextContent, Tool
from openai import OpenAI
# server.py → image-gen/ → mcp-servers/ → プロジェクトルート
DESIGN_BASE = Path(__file__).resolve().parents[2] / ".company" / "design" / "projects"
# MCPサーバーのインスタンスを作成
server = Server("image-gen")
# OpenAIクライアント(OPENAI_API_KEY 環境変数から自動取得)
client = OpenAI()
def _next_image_path(project: str) -> tuple[Path, Path, str, str]:
"""プロジェクトフォルダを準備し、次に保存すべきパス情報を返す"""
project_dir = DESIGN_BASE / project
images_dir = project_dir / "images"
prompts_dir = project_dir / "prompts"
images_dir.mkdir(parents=True, exist_ok=True)
prompts_dir.mkdir(parents=True, exist_ok=True)
today = date.today().strftime("%Y-%m-%d")
# 同日のファイル数をカウントして連番を決める
index = len(sorted(images_dir.glob(f"{today}-*.png"))) + 1
filename = f"{today}-{index:02d}.png"
return images_dir / filename, prompts_dir / f"{today}.md", today, filename
def _save_prompt(prompts_file: Path, project: str, today: str, filename: str, prompt: str) -> None:
write_header = not prompts_file.exists() # open前に確認
entry = f"\n## {filename}\n\n```\n{prompt}\n```\n"
with open(prompts_file, "a", encoding="utf-8") as f:
if write_header:
f.write(f"# {project} プロンプト記録 {today}\n")
f.write(entry)
@server.list_tools()
async def list_tools() -> list[Tool]:
"""Claude に公開するツールの一覧を返す"""
return [
Tool(
name="generate_image",
description="gpt-image-2でテキストから画像を生成し、デザイン部署のプロジェクトフォルダに保存する",
inputSchema={
"type": "object",
"properties": {
"prompt": {"type": "string", "description": "画像生成プロンプト(英語推奨、英語の方が精度が高い傾向があります)"},
"project": {"type": "string", "description": "プロジェクト名(例: my-project)"},
"size": {
"type": "string",
"enum": ["1024x1024", "1536x1024", "1024x1536"],
"default": "1024x1024",
"description": "画像サイズ",
},
},
"required": ["prompt", "project"],
},
),
Tool(
name="edit_image",
description="既存画像をベースにgpt-image-2でi2i編集し、デザイン部署のプロジェクトフォルダに保存する",
inputSchema={
"type": "object",
"properties": {
"image_path": {"type": "string", "description": "編集元画像のパス"},
"prompt": {"type": "string", "description": "編集内容のプロンプト(英語推奨)"},
"project": {"type": "string", "description": "プロジェクト名(保存先)"},
"mask_path": {
"type": "string",
"description": "マスク画像のパス(省略可)。透明部分が編集対象になる",
},
"size": {
"type": "string",
"enum": ["1024x1024", "1536x1024", "1024x1536"],
"default": "1024x1024",
"description": "出力サイズ",
},
},
"required": ["image_path", "prompt", "project"],
},
),
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
"""ツール呼び出しのエントリーポイント"""
# ── テキスト→画像生成 ──────────────────────────────────────
if name == "generate_image":
prompt = arguments["prompt"]
project = arguments["project"]
size = arguments.get("size", "1024x1024")
image_path, prompts_file, today, filename = _next_image_path(project)
# gpt-image-2はresponse_formatをサポートしておらず、デフォルトでb64_jsonで返される
response = client.images.generate(
model="gpt-image-2",
prompt=prompt,
size=size,
n=1,
)
if not (response.data and response.data[0].b64_json):
return [TextContent(type="text", text="画像を生成できませんでした")]
image_path.write_bytes(base64.b64decode(response.data[0].b64_json))
_save_prompt(prompts_file, project, today, filename, prompt)
return [TextContent(type="text", text=f"生成完了。\n保存先: {image_path}\nサイズ: {size}")]
# ── 画像→画像編集(i2i) ───────────────────────────────────
elif name == "edit_image":
src = arguments["image_path"]
prompt = arguments["prompt"]
project = arguments["project"]
mask_path = arguments.get("mask_path")
size = arguments.get("size", "1024x1024")
src_path = Path(src) if Path(src).is_absolute() else DESIGN_BASE / project / "images" / src
if not src_path.exists():
return [TextContent(type="text", text=f"画像が見つかりません: {src_path}")]
image_path, prompts_file, today, filename = _next_image_path(project)
with open(src_path, "rb") as img_f:
if mask_path:
# マスクあり: 透明部分だけを編集対象にして部分編集
with open(mask_path, "rb") as mask_f:
response = client.images.edit(
model="gpt-image-2",
image=img_f,
mask=mask_f,
prompt=prompt,
size=size,
n=1,
)
else:
# マスクなし: 画像全体をプロンプトに従って再構成
response = client.images.edit(
model="gpt-image-2",
image=img_f,
prompt=prompt,
size=size,
n=1,
)
if not (response.data and response.data[0].b64_json):
return [TextContent(type="text", text="画像を編集できませんでした")]
image_path.write_bytes(base64.b64decode(response.data[0].b64_json))
# プロンプト記録に元画像名も残す(どの画像を元にしたか追跡できる)
_save_prompt(prompts_file, project, today, filename, f"[i2i] base={src_path.name}\n{prompt}")
return [TextContent(type="text", text=f"編集完了。\n保存先: {image_path}\nサイズ: {size}")]
raise ValueError(f"Unknown tool: {name}")
async def main():
# stdio 経由でMCPプロトコルを処理するメインループ
async with stdio_server() as streams:
await server.run(streams[0], streams[1], server.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())
パッケージをインストールする
この記事では省略しますが pip install 前には仮想環境を作って適用することを推奨します
pip install -r mcp-servers/image-gen/requirements.txt
.mcp.json に登録する
プロジェクトルートに .mcp.json を作成します。
APIキーが含まれるため必ず.mcp.json を .gitignore に追加してください。
{
"mcpServers": {
"image-gen": {
"command": "py",
"args": ["mcp-servers/image-gen/server.py"],
"env": {
"OPENAI_API_KEY": "your-api-key-here"
}
}
}
}
※ Windowsの場合は py、macOS/Linuxの場合は python3 に変更してください。
部署を追加したときは、忘れずにClaude Codeを再起動してください。
実際に使ってみる
以下は著者が実際に行った会話です。
会話の内容は人によって変わります。
私:my-projectというプロジェクトで、眠たげな猫の画像を生成して
秘書(デザイン部):
生成完了。
保存先: .company\design\projects\my-project\images\2026-06-25-02.png
サイズ: 1024x1024
生成された画像は .company/design/projects/ 以下に自動保存され、使用したプロンプトも prompts/ に記録されます。
MCPサーバーは画像生成・保存のみ担当します。プロジェクトの概要やステータスを管理する [プロジェクト名].md は、秘書が初回作成します。
私:my-projectというプロジェクトを作って。動作確認用。
秘書(デザイン部):
プロジェクト「my-project」を作成しました。
.company/design/projects/my-project/my-project.md
i2i(画像→画像編集)も使えます。
私:2026-06-25-02.png をベースに猫を黒猫にして
秘書(デザイン部):
編集完了。
保存先: .company/design/projects/my-project/images/2026-06-25-03.png
あとがき
全3回を通じて、3種類の部署拡張パターンを紹介しました。
| パターン | 例 |
|---|---|
| 外部サービス不要・完全内部完結 | モチベーション部署 |
| 公式MCPで外部サービスと連携 | ナレッジ部署(Notion) |
| 自作MCPでAPIと連携 | デザイン部署(gpt-image-2) |
このシリーズを最後まで読んだあなたなら、いろんな使い方が思いつくはずです。
皆さんはどんな部署を作りましたか?よければ、コメント欄に書いてみてくださいね。

株式会社ECNはPHP、JavaScriptを中心にお客様のご要望に合わせたwebサービス、システム開発を承っております。 ビジネスの最初から最後までサポートを行い、お客様のイメージに合わせたWebサービス、システム開発、デザインを行います。

