Skip to content

Commit 156e661

Browse files
kpiwkoclaude
andcommitted
feat: replace plugins.yaml with ai-stack.yaml, add install-* commands
- Rename plugins.yaml → ai-stack.yaml; add mcps: section with all services (gmail, mcp-atlassian, gdrive, devlake mysql x2) - Add /ai-stack:install-plugins, install-skills, install-mcps commands with interactive picker, status display, and user/project/local scope - Register ai-stack plugin in marketplace.json so it's self-installable - README: new "Getting started with Claude Code" section; replace all raw claude mcp add blocks with /ai-stack:install-mcps references - justfile: remove install-* and check-images recipes (now Claude commands) - compose.yaml: fix ai-beacon description, remove stale local path refs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 497da32 commit 156e661

10 files changed

Lines changed: 332 additions & 172 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
{
22
"plugins": [
3+
{
4+
"name": "ai-stack",
5+
"path": "plugins/ai-stack",
6+
"description": "Maintenance commands for ai-stack repos: scaffold services, install plugins/skills/MCPs.",
7+
"version": "0.1.0"
8+
},
39
{
410
"name": "dev",
511
"path": "plugins/dev",

README.md

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Personal AI tooling stack: Podman Compose services for MCP servers, plus Claude
66

77
| Service | Port | Description |
88
|---|---|---|
9-
| ai-beacon | 17090 | Knowledge base / prompt library UI |
9+
| ai-beacon | 17090 | Session manager for multiple Claude sessions |
1010
| devlake-local-mysql-mcp | 17301 | Read-only MCP proxy for local DevLake MySQL |
1111
| devlake-prod-mysql-mcp | 17300 | Read-only MCP proxy for remote Konflux RDS |
1212
| gmail-mcp | 17633 | Gmail MCP server (search, draft, attachments) |
@@ -32,27 +32,31 @@ podman compose up -d gmail-mcp mcp-atlassian
3232

3333
Container images are built by CI and published to `ghcr.io/kpiwko/` — no local build needed.
3434

35-
## Plugins
35+
## Getting started with Claude Code
3636

37-
Claude Code plugins live in `plugins/`. Install them once inside Claude Code:
37+
Install the ai-stack plugin once:
3838

3939
```
40-
/plugin install dev@kpiwko/ai-stack
41-
/plugin install track@kpiwko/ai-stack
42-
/plugin install quarterly@kpiwko/ai-stack
40+
claude plugin install ai-stack@kpiwko/ai-stack
4341
```
4442

45-
Third-party plugins and bare skills are tracked in `plugins.yaml`. See `just install-plugins` and `just install-skills`.
43+
Then use it inside a Claude session to set up everything else:
44+
45+
```
46+
/ai-stack:install-plugins ← install dev, track, quarterly plugins
47+
/ai-stack:install-skills ← install bare skills (template-slide-deck, n8n-skills)
48+
/ai-stack:install-mcps ← register MCP servers with Claude Code
49+
```
50+
51+
All three commands are interactive: they show what's available, what's already installed,
52+
and let you pick scope (user / project / local) before making any changes.
4653

4754
## Just recipes
4855

4956
```bash
50-
just install-plugins # print /plugin install commands for Claude Code
51-
just install-skills # fetch and install bare skills from plugins.yaml (requires: yq, git)
52-
just check-images # verify compose.yaml uses no localhost/ images
53-
just up # podman compose up -d
54-
just down # podman compose down
55-
just status # podman compose ps
57+
just up # podman compose up -d
58+
just down # podman compose down
59+
just status # podman compose ps
5660
```
5761

5862
## gmail-mcp
@@ -64,62 +68,42 @@ reused automatically. On first run, authorize via browser:
6468
open http://localhost:17633/auth # complete Google Device Authorization
6569
```
6670

67-
Register with Claude Code once:
68-
69-
```bash
70-
claude mcp add --transport http --scope user gmail http://localhost:17633/mcp
71-
```
71+
Then register with Claude Code via `/ai-stack:install-mcps`.
7272

7373
## devlake-local-mysql-mcp
7474

75-
Connects to a DevLake MySQL instance running on the host at port 3306. Start DevLake first:
76-
77-
```bash
78-
cd ~/devel/work/devlake
79-
podman compose -f docker-compose-dev.yml up -d mysql
80-
```
81-
82-
Then start the MCP proxy:
83-
84-
```bash
85-
podman compose up -d devlake-local-mysql-mcp
86-
```
87-
88-
## Registering MCP servers with Claude Code
75+
Connects to a DevLake MySQL instance running on the host at port 3306. Start DevLake's
76+
MySQL service first, then register this MCP via `/ai-stack:install-mcps`. The command
77+
reads `$DEVLAKE_MCP_SECRET_KEY` from the environment — make sure `.env` is sourced first.
8978

90-
MySQL MCPs carry secrets and are registered **project-local** (`--scope local`), which writes
91-
to `.claude/settings.local.json` (gitignored). Run from the project that needs DB access:
79+
**Optional: connect via shared Podman network instead of host port**
9280

93-
```bash
94-
source ~/devel/local-ai/.env
81+
If DevLake runs in Podman Compose with a named network, you can attach this service to
82+
that network and reach MySQL by container name — no host port exposure needed.
9583

96-
claude mcp add --transport http --scope local devlake-prod-mysql-mcp \
97-
http://localhost:17300/mcp \
98-
--header "Authorization: Bearer ${KONFLUX_MCP_SECRET_KEY}"
84+
1. Find DevLake's network name: `podman network ls`
9985

100-
claude mcp add --transport http --scope local devlake-local-mysql-mcp \
101-
http://localhost:17301/mcp \
102-
--header "Authorization: Bearer ${DEVLAKE_MCP_SECRET_KEY}"
103-
```
86+
2. Declare it as external in `compose.yaml`:
87+
```yaml
88+
networks:
89+
ai-stack:
90+
driver: bridge
91+
devprod: # replace with DevLake's actual network name
92+
external: true
93+
```
10494
105-
Verify a server is responding before registering:
106-
107-
```bash
108-
curl -s -X POST http://localhost:17300/mcp \
109-
-H "Authorization: Bearer ${KONFLUX_MCP_SECRET_KEY}" \
110-
-H "Content-Type: application/json" \
111-
-H "Accept: application/json, text/event-stream" \
112-
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
113-
```
95+
3. Add the network to the service and update `MYSQL_HOST` to the MySQL container name:
96+
```yaml
97+
devlake-local-mysql-mcp:
98+
networks: [ai-stack, devprod]
99+
environment:
100+
MYSQL_HOST: mysql # replace with DevLake's MySQL container name
101+
```
114102

115103
## mcp-atlassian (Jira)
116104

117-
```bash
118-
podman compose up -d mcp-atlassian
119-
claude mcp add --transport http --scope user mcp-atlassian http://localhost:17000/mcp
120-
```
121-
122-
Credentials come from `.env`: `JIRA_URL`, `JIRA_USERNAME`, `JIRA_API_TOKEN`.
105+
Credentials come from `.env`: `JIRA_URL`, `JIRA_USERNAME`, `JIRA_API_TOKEN`. Start the
106+
service then register via `/ai-stack:install-mcps`.
123107

124108
## gdrive-mcp (Google Drive)
125109

@@ -131,11 +115,7 @@ npx @piotr-agier/google-drive-mcp auth
131115
```
132116

133117
This writes `credentials.json` and `tokens.json` into `~/.config/google-drive-mcp/`.
134-
135-
```bash
136-
podman compose up -d gdrive-mcp
137-
claude mcp add --transport http --scope user gdrive http://localhost:17100/mcp
138-
```
118+
Then start the service and register via `/ai-stack:install-mcps`.
139119

140120
## OpenShell sandboxes
141121

ai-stack.yaml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# ai-stack configuration
2+
#
3+
# plugins — Claude Code plugins with slash commands and agents
4+
# installed via /ai-stack:install-plugins
5+
#
6+
# skills — bare skills installed directly to .claude/skills/
7+
# installed via /ai-stack:install-skills
8+
#
9+
# mcps — MCP servers registered with Claude Code
10+
# installed via /ai-stack:install-mcps
11+
12+
plugins: []
13+
14+
# Example plugin entry:
15+
# - name: jira
16+
# source: openshift-eng/ai-helpers # GitHub owner/repo
17+
# version: "v1.2.0" # pin to a release tag
18+
19+
skills:
20+
- name: template-slide-deck
21+
source: toddward/claude-skills-playground
22+
path: template-slide-deck
23+
version: main
24+
25+
- name: n8n-skills
26+
source: czlonkowski/n8n-skills
27+
version: main
28+
29+
# Example skill entry:
30+
# - name: suggest-reviewers
31+
# source: openshift-eng/ai-helpers # GitHub owner/repo
32+
# path: plugins/git/skills/suggest-reviewers # path inside repo (omit for repo root)
33+
# version: "v1.2.0" # tag, branch, or commit
34+
# Scope (user/project/local) is chosen interactively via /ai-stack:install-skills
35+
36+
mcps:
37+
- name: gmail
38+
transport: http
39+
url: http://localhost:17633/mcp
40+
scope: user # default scope, overridable at install time
41+
42+
- name: mcp-atlassian
43+
transport: http
44+
url: http://localhost:17000/mcp
45+
scope: user
46+
47+
- name: gdrive
48+
transport: http
49+
url: http://localhost:17100/mcp
50+
scope: user
51+
52+
- name: devlake-prod-mysql-mcp
53+
transport: http
54+
url: http://localhost:17300/mcp
55+
headers:
56+
Authorization: "Bearer $KONFLUX_MCP_SECRET_KEY"
57+
scope: local # carries secrets — default to local (not committed)
58+
59+
- name: devlake-local-mysql-mcp
60+
transport: http
61+
url: http://localhost:17301/mcp
62+
headers:
63+
Authorization: "Bearer $DEVLAKE_MCP_SECRET_KEY"
64+
scope: local
65+
66+
# Example MCP entries:
67+
#
68+
# stdio transport (local process):
69+
# - name: my-mcp
70+
# transport: stdio
71+
# command: npx
72+
# args: ["-y", "@modelcontextprotocol/server-my-mcp"]
73+
# env:
74+
# API_KEY: $MY_API_KEY # references shell env var
75+
#
76+
# HTTP/SSE transport with auth header:
77+
# - name: my-mcp
78+
# transport: http # http | sse
79+
# url: http://localhost:8080/mcp
80+
# headers:
81+
# Authorization: "Bearer $MY_SECRET" # $VAR expanded from shell env
82+
# scope: local # user | project | local
83+
# # scope is a default — overridable at install time

compose.yaml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
# podman compose up -d <name> # start one service
1313
#
1414
# Services:
15-
# ai-beacon — AI Beacon knowledge base UI (port 17090)
15+
# ai-beacon — AI Beacon session manager for multiple Claude sessions (port 17090)
1616
# devlake-local-mysql-mcp — MySQL MCP proxy for local DevLake DB (port 17301)
17-
# Requires devlake MySQL running separately via
18-
# ~/devel/work/devlake docker-compose-dev.yml (port 3306).
17+
# Requires DevLake MySQL running on host port 3306.
1918
# devlake-prod-mysql-mcp — MySQL MCP proxy for remote Konflux RDS (port 17300)
2019
# gmail-mcp — Gmail MCP server, streamable HTTP transport (port 17633)
2120
# mcp-atlassian — Jira MCP server, streamable HTTP transport (port 17000)
@@ -33,7 +32,7 @@ volumes:
3332
services:
3433

3534
##############################################################################
36-
# AI Beacon — knowledge base / prompt library UI
35+
# AI Beacon — session manager for multiple Claude sessions
3736
# URL: http://localhost:17090
3837
##############################################################################
3938
ai-beacon:
@@ -54,7 +53,6 @@ services:
5453
# MCP endpoint: http://localhost:17301/mcp (streamable HTTP transport)
5554
#
5655
# Connects to DevLake MySQL via host.containers.internal:3306.
57-
# Start DevLake first: cd ~/devel/work/devlake && podman compose -f docker-compose-dev.yml up -d
5856
##############################################################################
5957
devlake-local-mysql-mcp:
6058
image: ghcr.io/kpiwko/mcp-mysql:latest

justfile

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,6 @@
11
default:
22
@just --list
33

4-
# Print Claude Code /plugin install commands (run them inside Claude Code)
5-
install-plugins:
6-
#!/usr/bin/env bash
7-
set -euo pipefail
8-
count=$(yq '.plugins | length' plugins.yaml)
9-
if [ "$count" -eq 0 ]; then
10-
echo "No plugins configured in plugins.yaml"
11-
exit 0
12-
fi
13-
echo "Run these inside Claude Code:"
14-
for i in $(seq 0 $((count - 1))); do
15-
name=$(yq ".plugins[$i].name" plugins.yaml)
16-
source=$(yq ".plugins[$i].source" plugins.yaml)
17-
echo " /plugin install ${name}@${source}"
18-
done
19-
20-
# Install bare skills from 3rd party repos (requires: yq, git)
21-
install-skills:
22-
#!/usr/bin/env bash
23-
set -euo pipefail
24-
count=$(yq '.skills | length' plugins.yaml)
25-
if [ "$count" -eq 0 ]; then
26-
echo "No skills configured in plugins.yaml"
27-
exit 0
28-
fi
29-
for i in $(seq 0 $((count - 1))); do
30-
name=$(yq ".skills[$i].name" plugins.yaml)
31-
source=$(yq ".skills[$i].source" plugins.yaml)
32-
path=$(yq ".skills[$i].path // \"\"" plugins.yaml)
33-
version=$(yq ".skills[$i].version // \"main\"" plugins.yaml)
34-
scope=$(yq ".skills[$i].scope // \"project\"" plugins.yaml)
35-
36-
if [ "$scope" = "global" ]; then
37-
target="$HOME/.claude/skills/$name"
38-
else
39-
target=".claude/skills/$name"
40-
fi
41-
42-
echo "Installing $name$target"
43-
tmpdir=$(mktemp -d)
44-
trap "rm -rf $tmpdir" EXIT
45-
46-
git clone --depth 1 --filter=blob:none --sparse --branch "$version" \
47-
"https://github.com/$source" "$tmpdir" 2>/dev/null
48-
49-
if [ -n "$path" ]; then
50-
git -C "$tmpdir" sparse-checkout set "$path" 2>/dev/null
51-
mkdir -p "$target"
52-
cp -r "$tmpdir/$path/." "$target/"
53-
else
54-
mkdir -p "$target"
55-
cp -r "$tmpdir/." "$target/"
56-
fi
57-
58-
trap - EXIT
59-
rm -rf "$tmpdir"
60-
echo " ✓ done"
61-
done
62-
63-
# Check compose services all use ghcr.io images (not localhost/)
64-
check-images:
65-
@grep -n 'image: localhost/' compose.yaml && echo "FAIL: localhost/ images found" && exit 1 || echo "OK: all images use remote registry"
66-
674
# Start all compose services
685
up:
696
podman compose up -d

plugins.yaml

Lines changed: 0 additions & 41 deletions
This file was deleted.

plugins/ai-stack/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ automatically when working inside the ai-stack repository.
1010
| `/ai-stack:add-service <name>` | Scaffold Containerfile, multi-arch CI workflow, and compose.yaml entry |
1111
| `/ai-stack:add-workflow <name>` | Generate multi-arch Buildah workflow for an existing service |
1212
| `/ai-stack:check-images` | Verify all compose.yaml services use remote registry images |
13+
| `/ai-stack:install-plugins [name\|all]` | Install ai-stack and 3rd party plugins (user/project/local scope) |
14+
| `/ai-stack:install-skills [name\|all]` | Install bare skills from ai-stack.yaml (user/project/local scope) |
15+
| `/ai-stack:install-mcps [name\|all]` | Register MCP servers from ai-stack.yaml with Claude Code (user/project/local scope) |

0 commit comments

Comments
 (0)