image-generation-mcp 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- image_generation_mcp-1.0.0/.github/codeql/codeql-config.yml +1 -0
- image_generation_mcp-1.0.0/.github/workflows/ci.yml +165 -0
- image_generation_mcp-1.0.0/.github/workflows/claude-code-review.yml +54 -0
- image_generation_mcp-1.0.0/.github/workflows/claude.yml +39 -0
- image_generation_mcp-1.0.0/.github/workflows/codeql.yml +31 -0
- image_generation_mcp-1.0.0/.github/workflows/docs.yml +48 -0
- image_generation_mcp-1.0.0/.github/workflows/release.yml +232 -0
- image_generation_mcp-1.0.0/.gitignore +21 -0
- image_generation_mcp-1.0.0/.gitleaks.toml +8 -0
- image_generation_mcp-1.0.0/CHANGELOG.md +7 -0
- image_generation_mcp-1.0.0/CLAUDE.md +46 -0
- image_generation_mcp-1.0.0/Dockerfile +44 -0
- image_generation_mcp-1.0.0/LICENSE +21 -0
- image_generation_mcp-1.0.0/PKG-INFO +337 -0
- image_generation_mcp-1.0.0/README.md +294 -0
- image_generation_mcp-1.0.0/TEMPLATE.md +121 -0
- image_generation_mcp-1.0.0/codecov.yml +32 -0
- image_generation_mcp-1.0.0/compose.yml +23 -0
- image_generation_mcp-1.0.0/docker-entrypoint.sh +48 -0
- image_generation_mcp-1.0.0/docs/configuration.md +84 -0
- image_generation_mcp-1.0.0/docs/decisions/0001-multi-provider-architecture.md +94 -0
- image_generation_mcp-1.0.0/docs/decisions/0002-provider-protocol-and-registry.md +92 -0
- image_generation_mcp-1.0.0/docs/decisions/0003-a1111-model-aware-presets.md +60 -0
- image_generation_mcp-1.0.0/docs/decisions/0004-keyword-based-provider-selection.md +82 -0
- image_generation_mcp-1.0.0/docs/decisions/0005-hybrid-background-tasks.md +93 -0
- image_generation_mcp-1.0.0/docs/decisions/0006-image-asset-model.md +130 -0
- image_generation_mcp-1.0.0/docs/deployment/docker.md +37 -0
- image_generation_mcp-1.0.0/docs/deployment/oidc.md +209 -0
- image_generation_mcp-1.0.0/docs/design/provider-system.md +250 -0
- image_generation_mcp-1.0.0/docs/getting-started/claude-code.md +72 -0
- image_generation_mcp-1.0.0/docs/getting-started/claude-desktop.md +110 -0
- image_generation_mcp-1.0.0/docs/getting-started/installation.md +66 -0
- image_generation_mcp-1.0.0/docs/guides/authentication.md +220 -0
- image_generation_mcp-1.0.0/docs/guides/image-assets.md +31 -0
- image_generation_mcp-1.0.0/docs/guides/prompt-writing.md +183 -0
- image_generation_mcp-1.0.0/docs/index.md +99 -0
- image_generation_mcp-1.0.0/docs/prompts.md +55 -0
- image_generation_mcp-1.0.0/docs/providers/a1111.md +112 -0
- image_generation_mcp-1.0.0/docs/providers/index.md +55 -0
- image_generation_mcp-1.0.0/docs/providers/openai.md +93 -0
- image_generation_mcp-1.0.0/docs/providers/placeholder.md +42 -0
- image_generation_mcp-1.0.0/docs/resources.md +132 -0
- image_generation_mcp-1.0.0/docs/tools.md +109 -0
- image_generation_mcp-1.0.0/examples/bearer-auth.env +5 -0
- image_generation_mcp-1.0.0/examples/oidc.env +9 -0
- image_generation_mcp-1.0.0/mkdocs.yml +126 -0
- image_generation_mcp-1.0.0/pyproject.toml +131 -0
- image_generation_mcp-1.0.0/scripts/rename.sh +65 -0
- image_generation_mcp-1.0.0/server.json +37 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/__init__.py +1 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/_server_deps.py +96 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/_server_prompts.py +188 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/_server_resources.py +212 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/_server_tools.py +180 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/cli.py +143 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/config.py +137 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/mcp_server.py +265 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/processing.py +199 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/providers/__init__.py +24 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/providers/a1111.py +239 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/providers/openai.py +222 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/providers/placeholder.py +115 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/providers/selector.py +126 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/providers/types.py +113 -0
- image_generation_mcp-1.0.0/src/image_generation_mcp/service.py +377 -0
- image_generation_mcp-1.0.0/tests/__init__.py +0 -0
- image_generation_mcp-1.0.0/tests/conftest.py +18 -0
- image_generation_mcp-1.0.0/tests/test_a1111_provider.py +242 -0
- image_generation_mcp-1.0.0/tests/test_image_assets.py +188 -0
- image_generation_mcp-1.0.0/tests/test_mcp_server.py +117 -0
- image_generation_mcp-1.0.0/tests/test_openai_provider.py +242 -0
- image_generation_mcp-1.0.0/tests/test_placeholder.py +75 -0
- image_generation_mcp-1.0.0/tests/test_processing.py +185 -0
- image_generation_mcp-1.0.0/tests/test_prompts.py +32 -0
- image_generation_mcp-1.0.0/tests/test_resources.py +168 -0
- image_generation_mcp-1.0.0/tests/test_selector.py +100 -0
- image_generation_mcp-1.0.0/tests/test_service.py +78 -0
- image_generation_mcp-1.0.0/tests/test_tasks.py +46 -0
- image_generation_mcp-1.0.0/tests/test_types.py +121 -0
- image_generation_mcp-1.0.0/uv.lock +2975 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
name: "CodeQL config"
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
lint:
|
|
12
|
+
name: Lint
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v4
|
|
19
|
+
with:
|
|
20
|
+
version: "latest"
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
run: uv python install 3.12
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: uv sync --all-extras
|
|
27
|
+
|
|
28
|
+
- name: Run ruff check
|
|
29
|
+
run: uv run ruff check src/ tests/
|
|
30
|
+
|
|
31
|
+
- name: Run ruff format check
|
|
32
|
+
run: uv run ruff format --check src/ tests/
|
|
33
|
+
|
|
34
|
+
typecheck:
|
|
35
|
+
name: Type Check
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- name: Install uv
|
|
41
|
+
uses: astral-sh/setup-uv@v4
|
|
42
|
+
with:
|
|
43
|
+
version: "latest"
|
|
44
|
+
|
|
45
|
+
- name: Set up Python
|
|
46
|
+
run: uv python install 3.12
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies
|
|
49
|
+
run: uv sync --all-extras
|
|
50
|
+
|
|
51
|
+
- name: Run mypy
|
|
52
|
+
run: uv run mypy src/
|
|
53
|
+
|
|
54
|
+
test:
|
|
55
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
continue-on-error: ${{ matrix.experimental || false }}
|
|
58
|
+
permissions:
|
|
59
|
+
contents: read
|
|
60
|
+
statuses: write
|
|
61
|
+
strategy:
|
|
62
|
+
fail-fast: false
|
|
63
|
+
matrix:
|
|
64
|
+
include:
|
|
65
|
+
- python-version: "3.11"
|
|
66
|
+
experimental: false
|
|
67
|
+
- python-version: "3.12"
|
|
68
|
+
experimental: false
|
|
69
|
+
- python-version: "3.13"
|
|
70
|
+
experimental: false
|
|
71
|
+
- python-version: "3.14"
|
|
72
|
+
experimental: true
|
|
73
|
+
steps:
|
|
74
|
+
- uses: actions/checkout@v4
|
|
75
|
+
|
|
76
|
+
- name: Install uv
|
|
77
|
+
uses: astral-sh/setup-uv@v4
|
|
78
|
+
with:
|
|
79
|
+
version: "latest"
|
|
80
|
+
|
|
81
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
82
|
+
run: uv python install ${{ matrix.python-version }}
|
|
83
|
+
|
|
84
|
+
- name: Install dependencies
|
|
85
|
+
run: uv sync --all-extras
|
|
86
|
+
|
|
87
|
+
- name: Run tests with coverage
|
|
88
|
+
run: uv run pytest --cov --cov-report=xml
|
|
89
|
+
|
|
90
|
+
- name: Upload coverage to Codecov
|
|
91
|
+
if: matrix.python-version == '3.13'
|
|
92
|
+
uses: codecov/codecov-action@v5
|
|
93
|
+
with:
|
|
94
|
+
files: ./coverage.xml
|
|
95
|
+
fail_ci_if_error: false
|
|
96
|
+
override_pr: ${{ github.event.pull_request.number }}
|
|
97
|
+
env:
|
|
98
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
99
|
+
|
|
100
|
+
- name: Post codecov/patch status for non-Python PRs
|
|
101
|
+
if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
|
|
102
|
+
uses: actions/github-script@v7
|
|
103
|
+
with:
|
|
104
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
105
|
+
script: |
|
|
106
|
+
const { data: files } = await github.rest.pulls.listFiles({
|
|
107
|
+
owner: context.repo.owner,
|
|
108
|
+
repo: context.repo.repo,
|
|
109
|
+
pull_number: context.payload.pull_request.number,
|
|
110
|
+
});
|
|
111
|
+
const hasPythonSourceChanges = files.some(
|
|
112
|
+
f => f.filename.endsWith('.py')
|
|
113
|
+
);
|
|
114
|
+
if (!hasPythonSourceChanges) {
|
|
115
|
+
const headSha = context.payload.pull_request.head.sha;
|
|
116
|
+
core.info(`No Python source changes — posting codecov/patch: success to ${headSha}`);
|
|
117
|
+
await github.rest.repos.createCommitStatus({
|
|
118
|
+
owner: context.repo.owner,
|
|
119
|
+
repo: context.repo.repo,
|
|
120
|
+
sha: headSha,
|
|
121
|
+
state: 'success',
|
|
122
|
+
context: 'codecov/patch',
|
|
123
|
+
description: 'Coverage not affected',
|
|
124
|
+
target_url: 'https://app.codecov.io/gh/pvliesdonk/image-generation-mcp',
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
core.info('Python source changes detected — Codecov will post patch status');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
audit:
|
|
131
|
+
name: Dependency Audit
|
|
132
|
+
runs-on: ubuntu-latest
|
|
133
|
+
permissions:
|
|
134
|
+
contents: read
|
|
135
|
+
steps:
|
|
136
|
+
- uses: actions/checkout@v4
|
|
137
|
+
|
|
138
|
+
- name: Install uv
|
|
139
|
+
uses: astral-sh/setup-uv@v4
|
|
140
|
+
with:
|
|
141
|
+
version: "latest"
|
|
142
|
+
|
|
143
|
+
- name: Set up Python
|
|
144
|
+
run: uv python install 3.12
|
|
145
|
+
|
|
146
|
+
- name: Export dependency list (excluding local project)
|
|
147
|
+
run: uv export --all-extras --frozen --no-emit-project --no-hashes -o ${{ runner.temp }}/requirements.txt
|
|
148
|
+
|
|
149
|
+
- name: Run pip-audit
|
|
150
|
+
run: uvx pip-audit --strict --progress-spinner off -r ${{ runner.temp }}/requirements.txt
|
|
151
|
+
|
|
152
|
+
secrets:
|
|
153
|
+
name: Secret Detection
|
|
154
|
+
runs-on: ubuntu-latest
|
|
155
|
+
permissions:
|
|
156
|
+
contents: read
|
|
157
|
+
steps:
|
|
158
|
+
- uses: actions/checkout@v4
|
|
159
|
+
with:
|
|
160
|
+
fetch-depth: 0
|
|
161
|
+
|
|
162
|
+
- name: Run gitleaks
|
|
163
|
+
uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2
|
|
164
|
+
env:
|
|
165
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Claude Code Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
claude-review:
|
|
9
|
+
if: github.actor != 'dependabot[bot]'
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
pull-requests: write
|
|
14
|
+
id-token: write
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout repository
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 1
|
|
21
|
+
|
|
22
|
+
- name: Run Claude Code Review
|
|
23
|
+
id: claude-review
|
|
24
|
+
uses: anthropics/claude-code-action@v1
|
|
25
|
+
continue-on-error: true
|
|
26
|
+
with:
|
|
27
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
28
|
+
track_progress: true
|
|
29
|
+
prompt: |
|
|
30
|
+
REPO: ${{ github.repository }}
|
|
31
|
+
PR NUMBER: ${{ github.event.pull_request.number }}
|
|
32
|
+
|
|
33
|
+
Perform a DIFFERENTIAL code review. Only review the CHANGES in this PR.
|
|
34
|
+
|
|
35
|
+
Steps:
|
|
36
|
+
1. Run `gh pr diff ${{ github.event.pull_request.number }}` to see what changed
|
|
37
|
+
2. Read CLAUDE.md for project conventions
|
|
38
|
+
3. Read docs/design.md for the authoritative design specification
|
|
39
|
+
4. Review the changed code for:
|
|
40
|
+
- Bugs or logic errors
|
|
41
|
+
- Security issues
|
|
42
|
+
- Convention violations (from CLAUDE.md)
|
|
43
|
+
- Missing tests for new code
|
|
44
|
+
- Type safety issues
|
|
45
|
+
- Design conformance: does the implementation match docs/design.md?
|
|
46
|
+
Check data types, method signatures, error handling, and database schema.
|
|
47
|
+
|
|
48
|
+
Use `mcp__github_inline_comment__create_inline_comment` for specific line feedback.
|
|
49
|
+
Use `gh pr comment` for summary feedback.
|
|
50
|
+
|
|
51
|
+
Be concise. Focus on actionable issues. Don't comment on unchanged code.
|
|
52
|
+
|
|
53
|
+
claude_args: |
|
|
54
|
+
--allowedTools mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr comment:*),Read,Grep,Glob
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Claude Code
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
issues:
|
|
9
|
+
types: [opened, assigned]
|
|
10
|
+
pull_request_review:
|
|
11
|
+
types: [submitted]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude:
|
|
15
|
+
if: |
|
|
16
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
17
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
18
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
19
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
pull-requests: read
|
|
24
|
+
issues: read
|
|
25
|
+
id-token: write
|
|
26
|
+
actions: read
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout repository
|
|
29
|
+
uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
|
|
33
|
+
- name: Run Claude Code
|
|
34
|
+
id: claude
|
|
35
|
+
uses: anthropics/claude-code-action@v1
|
|
36
|
+
with:
|
|
37
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
38
|
+
additional_permissions: |
|
|
39
|
+
actions: read
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1" # Weekly on Monday at 06:00 UTC
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
actions: read
|
|
13
|
+
contents: read
|
|
14
|
+
security-events: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
analyze:
|
|
18
|
+
name: CodeQL Analysis
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Initialize CodeQL
|
|
24
|
+
uses: github/codeql-action/init@v3
|
|
25
|
+
with:
|
|
26
|
+
languages: python
|
|
27
|
+
queries: security-extended
|
|
28
|
+
config-file: .github/codeql/codeql-config.yml
|
|
29
|
+
|
|
30
|
+
- name: Perform CodeQL Analysis
|
|
31
|
+
uses: github/codeql-action/analyze@v3
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
pages: write
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: "pages"
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
deploy:
|
|
17
|
+
environment:
|
|
18
|
+
name: github-pages
|
|
19
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v4
|
|
26
|
+
with:
|
|
27
|
+
version: "latest"
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
run: uv python install 3.12
|
|
31
|
+
|
|
32
|
+
- name: Install docs dependencies
|
|
33
|
+
run: uv sync --extra docs
|
|
34
|
+
|
|
35
|
+
- name: Build docs
|
|
36
|
+
run: uv run mkdocs build
|
|
37
|
+
|
|
38
|
+
- name: Setup Pages
|
|
39
|
+
uses: actions/configure-pages@v5
|
|
40
|
+
|
|
41
|
+
- name: Upload artifact
|
|
42
|
+
uses: actions/upload-pages-artifact@v3
|
|
43
|
+
with:
|
|
44
|
+
path: site/
|
|
45
|
+
|
|
46
|
+
- name: Deploy to GitHub Pages
|
|
47
|
+
id: deployment
|
|
48
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
force:
|
|
7
|
+
description: 'Force version bump (leave empty for auto)'
|
|
8
|
+
type: choice
|
|
9
|
+
default: ''
|
|
10
|
+
options:
|
|
11
|
+
- ''
|
|
12
|
+
- patch
|
|
13
|
+
- minor
|
|
14
|
+
- major
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
release:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
concurrency:
|
|
23
|
+
group: release
|
|
24
|
+
cancel-in-progress: false
|
|
25
|
+
|
|
26
|
+
permissions:
|
|
27
|
+
contents: write
|
|
28
|
+
id-token: write
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout repository
|
|
32
|
+
uses: actions/checkout@v4
|
|
33
|
+
with:
|
|
34
|
+
fetch-depth: 0
|
|
35
|
+
ref: ${{ github.ref_name }}
|
|
36
|
+
token: ${{ secrets.RELEASE_TOKEN }}
|
|
37
|
+
|
|
38
|
+
- name: Install uv
|
|
39
|
+
uses: astral-sh/setup-uv@v4
|
|
40
|
+
with:
|
|
41
|
+
version: "0.6"
|
|
42
|
+
|
|
43
|
+
- name: Setup Python
|
|
44
|
+
run: uv python install 3.12
|
|
45
|
+
|
|
46
|
+
- name: Semantic Version Release
|
|
47
|
+
id: release
|
|
48
|
+
uses: python-semantic-release/python-semantic-release@v10.5.3
|
|
49
|
+
with:
|
|
50
|
+
github_token: ${{ secrets.RELEASE_TOKEN }}
|
|
51
|
+
git_committer_name: "github-actions"
|
|
52
|
+
git_committer_email: "actions@users.noreply.github.com"
|
|
53
|
+
force: ${{ inputs.force }}
|
|
54
|
+
|
|
55
|
+
- name: Update server.json to released version
|
|
56
|
+
if: steps.release.outputs.released == 'true'
|
|
57
|
+
env:
|
|
58
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
59
|
+
run: |
|
|
60
|
+
jq --arg v "$VERSION" '
|
|
61
|
+
.version = $v |
|
|
62
|
+
.packages |= map(
|
|
63
|
+
if .registryType == "pypi" then .version = $v
|
|
64
|
+
elif .registryType == "oci" then .identifier = ("ghcr.io/pvliesdonk/image-generation-mcp:" + $v)
|
|
65
|
+
else . end
|
|
66
|
+
)
|
|
67
|
+
' server.json > server.json.tmp
|
|
68
|
+
mv server.json.tmp server.json
|
|
69
|
+
git config user.name "github-actions"
|
|
70
|
+
git config user.email "actions@users.noreply.github.com"
|
|
71
|
+
git add server.json
|
|
72
|
+
git diff --cached --quiet || git commit -m "chore: update server.json to v${VERSION} [skip ci]"
|
|
73
|
+
git push
|
|
74
|
+
|
|
75
|
+
- name: Build package
|
|
76
|
+
if: steps.release.outputs.released == 'true'
|
|
77
|
+
run: uv build
|
|
78
|
+
|
|
79
|
+
- name: Generate SBOM
|
|
80
|
+
if: steps.release.outputs.released == 'true'
|
|
81
|
+
uses: anchore/sbom-action@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1
|
|
82
|
+
with:
|
|
83
|
+
path: .
|
|
84
|
+
format: cyclonedx-json
|
|
85
|
+
output-file: sbom.cdx.json
|
|
86
|
+
upload-artifact: false
|
|
87
|
+
upload-release-assets: false
|
|
88
|
+
|
|
89
|
+
- name: Upload SBOM to GitHub Release
|
|
90
|
+
if: steps.release.outputs.released == 'true'
|
|
91
|
+
run: gh release upload ${{ steps.release.outputs.tag }} sbom.cdx.json
|
|
92
|
+
env:
|
|
93
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
94
|
+
|
|
95
|
+
- name: Upload to GitHub Release Assets
|
|
96
|
+
uses: python-semantic-release/publish-action@v10.5.3
|
|
97
|
+
if: steps.release.outputs.released == 'true'
|
|
98
|
+
with:
|
|
99
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
100
|
+
tag: ${{ steps.release.outputs.tag }}
|
|
101
|
+
|
|
102
|
+
- name: Upload build artifacts
|
|
103
|
+
if: steps.release.outputs.released == 'true'
|
|
104
|
+
uses: actions/upload-artifact@v4
|
|
105
|
+
with:
|
|
106
|
+
name: dist
|
|
107
|
+
path: dist/
|
|
108
|
+
|
|
109
|
+
outputs:
|
|
110
|
+
released: ${{ steps.release.outputs.released }}
|
|
111
|
+
version: ${{ steps.release.outputs.version }}
|
|
112
|
+
tag: ${{ steps.release.outputs.tag }}
|
|
113
|
+
|
|
114
|
+
publish-pypi:
|
|
115
|
+
needs: release
|
|
116
|
+
if: needs.release.outputs.released == 'true'
|
|
117
|
+
runs-on: ubuntu-latest
|
|
118
|
+
environment:
|
|
119
|
+
name: pypi
|
|
120
|
+
url: https://pypi.org/p/image-generation-mcp
|
|
121
|
+
|
|
122
|
+
permissions:
|
|
123
|
+
id-token: write
|
|
124
|
+
|
|
125
|
+
steps:
|
|
126
|
+
- name: Download build artifacts
|
|
127
|
+
uses: actions/download-artifact@v4
|
|
128
|
+
with:
|
|
129
|
+
name: dist
|
|
130
|
+
path: dist/
|
|
131
|
+
|
|
132
|
+
- name: Publish to PyPI
|
|
133
|
+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1
|
|
134
|
+
with:
|
|
135
|
+
packages-dir: dist/
|
|
136
|
+
print-hash: true
|
|
137
|
+
verbose: true
|
|
138
|
+
|
|
139
|
+
publish-docker:
|
|
140
|
+
needs: release
|
|
141
|
+
if: needs.release.outputs.released == 'true'
|
|
142
|
+
runs-on: ubuntu-latest
|
|
143
|
+
|
|
144
|
+
permissions:
|
|
145
|
+
contents: read
|
|
146
|
+
packages: write
|
|
147
|
+
id-token: write
|
|
148
|
+
attestations: write
|
|
149
|
+
|
|
150
|
+
env:
|
|
151
|
+
REGISTRY: ghcr.io
|
|
152
|
+
IMAGE_NAME: ${{ github.repository }}
|
|
153
|
+
|
|
154
|
+
steps:
|
|
155
|
+
- name: Checkout repository
|
|
156
|
+
uses: actions/checkout@v4
|
|
157
|
+
with:
|
|
158
|
+
ref: ${{ needs.release.outputs.tag }}
|
|
159
|
+
fetch-depth: 1
|
|
160
|
+
|
|
161
|
+
- name: Set up QEMU
|
|
162
|
+
uses: docker/setup-qemu-action@v3
|
|
163
|
+
|
|
164
|
+
- name: Set up Docker Buildx
|
|
165
|
+
uses: docker/setup-buildx-action@v3
|
|
166
|
+
|
|
167
|
+
- name: Log in to Container Registry
|
|
168
|
+
uses: docker/login-action@v3
|
|
169
|
+
with:
|
|
170
|
+
registry: ${{ env.REGISTRY }}
|
|
171
|
+
username: ${{ github.actor }}
|
|
172
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
173
|
+
|
|
174
|
+
- name: Extract version components
|
|
175
|
+
id: version
|
|
176
|
+
env:
|
|
177
|
+
VERSION: ${{ needs.release.outputs.version }}
|
|
178
|
+
run: |
|
|
179
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
180
|
+
echo "major=$(echo "$VERSION" | cut -d. -f1)" >> $GITHUB_OUTPUT
|
|
181
|
+
echo "minor=$(echo "$VERSION" | cut -d. -f1-2)" >> $GITHUB_OUTPUT
|
|
182
|
+
|
|
183
|
+
- name: Extract metadata (tags, labels)
|
|
184
|
+
id: meta
|
|
185
|
+
uses: docker/metadata-action@v5
|
|
186
|
+
with:
|
|
187
|
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
188
|
+
tags: |
|
|
189
|
+
type=raw,value=latest
|
|
190
|
+
type=raw,value=v${{ steps.version.outputs.version }}
|
|
191
|
+
type=raw,value=v${{ steps.version.outputs.minor }}
|
|
192
|
+
type=raw,value=v${{ steps.version.outputs.major }}
|
|
193
|
+
labels: |
|
|
194
|
+
org.opencontainers.image.title=image-generation-mcp
|
|
195
|
+
org.opencontainers.image.description=FastMCP server template
|
|
196
|
+
org.opencontainers.image.vendor=pvliesdonk
|
|
197
|
+
|
|
198
|
+
- name: Build and push Docker image
|
|
199
|
+
id: build-push
|
|
200
|
+
uses: docker/build-push-action@v6
|
|
201
|
+
with:
|
|
202
|
+
context: .
|
|
203
|
+
platforms: linux/amd64,linux/arm64
|
|
204
|
+
push: true
|
|
205
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
206
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
207
|
+
cache-from: type=gha
|
|
208
|
+
cache-to: type=gha,mode=max
|
|
209
|
+
|
|
210
|
+
- name: Generate artifact attestation
|
|
211
|
+
uses: actions/attest-build-provenance@v2
|
|
212
|
+
with:
|
|
213
|
+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
214
|
+
subject-digest: ${{ steps.build-push.outputs.digest }}
|
|
215
|
+
push-to-registry: true
|
|
216
|
+
|
|
217
|
+
- name: Generate SBOM for Docker image
|
|
218
|
+
uses: anchore/sbom-action@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1
|
|
219
|
+
with:
|
|
220
|
+
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-push.outputs.digest }}
|
|
221
|
+
format: cyclonedx-json
|
|
222
|
+
output-file: sbom-docker.cdx.json
|
|
223
|
+
upload-artifact: false
|
|
224
|
+
upload-release-assets: false
|
|
225
|
+
|
|
226
|
+
- name: Attest Docker SBOM
|
|
227
|
+
uses: actions/attest-sbom@v2
|
|
228
|
+
with:
|
|
229
|
+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
230
|
+
subject-digest: ${{ steps.build-push.outputs.digest }}
|
|
231
|
+
sbom-path: sbom-docker.cdx.json
|
|
232
|
+
push-to-registry: true
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# image-generation-mcp
|
|
2
|
+
|
|
3
|
+
FastMCP server scaffold. See [TEMPLATE.md](TEMPLATE.md) for customisation guide.
|
|
4
|
+
|
|
5
|
+
## Project Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/image_generation_mcp/
|
|
9
|
+
mcp_server.py -- FastMCP server factory + auth wiring (don't modify)
|
|
10
|
+
config.py -- env var loading; add domain config fields here
|
|
11
|
+
cli.py -- CLI entry point (serve command)
|
|
12
|
+
_server_deps.py -- lifespan + Depends() DI; replace placeholder service
|
|
13
|
+
_server_tools.py -- MCP tools; replace example tools with domain tools
|
|
14
|
+
_server_resources.py -- MCP resources; add domain resources here
|
|
15
|
+
_server_prompts.py -- MCP prompts; add domain prompts here
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Conventions
|
|
19
|
+
|
|
20
|
+
- Python 3.11+
|
|
21
|
+
- `uv` for package management, `ruff` for linting/formatting (line length 88)
|
|
22
|
+
- `hatchling` build backend
|
|
23
|
+
- Conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`
|
|
24
|
+
- Google-style docstrings on all public functions
|
|
25
|
+
- `logging.getLogger(__name__)` throughout, no `print()`
|
|
26
|
+
- Type hints everywhere
|
|
27
|
+
|
|
28
|
+
## Key Patterns
|
|
29
|
+
|
|
30
|
+
- Library is sync; MCP layer uses `asyncio.to_thread()` for blocking calls
|
|
31
|
+
- Write tools tagged `tags={"write"}`, hidden via `mcp.disable(tags={"write"})` in read-only mode
|
|
32
|
+
- Auth: `_build_bearer_auth()` + `_build_oidc_auth()` called in `create_server()`; MultiAuth when both set
|
|
33
|
+
- `_ENV_PREFIX` in `config.py` controls all env var names — change once, affects everything
|
|
34
|
+
|
|
35
|
+
## Documentation
|
|
36
|
+
|
|
37
|
+
Every PR that changes user-facing behavior must update the corresponding documentation:
|
|
38
|
+
|
|
39
|
+
- **New/changed tools or resources** → update `docs/tools.md` and `docs/resources.md`
|
|
40
|
+
- **New/changed env vars** → update `docs/configuration.md` AND the README config table
|
|
41
|
+
- **New/changed provider behavior** → update the provider's page in `docs/providers/`
|
|
42
|
+
- **New MCP client configuration** → update `docs/getting-started/claude-desktop.md` or `claude-code.md`
|
|
43
|
+
|
|
44
|
+
The architect-reviewer conformance check includes documentation currency. A PR that adds a tool without documenting it is incomplete.
|
|
45
|
+
|
|
46
|
+
Internal design docs (`docs/design/`, `docs/decisions/`) are developer reference — they are NOT part of the mkdocs site. ADRs are created/updated as part of implementation issues, not documentation issues.
|