Skip to content

Commit f944dfe

Browse files
authored
Merge branch 'main' into feat/add-kion-mcp
2 parents 73c7844 + 85d6d2a commit f944dfe

File tree

25 files changed

+1498
-347
lines changed

25 files changed

+1498
-347
lines changed

.github/workflows/build-and-publish.yml

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
uses: actions/checkout@v5
2626

2727
- name: Set up Go
28-
uses: actions/setup-go@v5
28+
uses: actions/setup-go@v6
2929
with:
3030
go-version-file: 'go.mod'
3131
cache: true
@@ -44,7 +44,7 @@ jobs:
4444
uses: actions/checkout@v5
4545

4646
- name: Set up Go
47-
uses: actions/setup-go@v5
47+
uses: actions/setup-go@v6
4848
with:
4949
go-version-file: 'go.mod'
5050
cache: true
@@ -83,26 +83,29 @@ jobs:
8383
fetch-depth: 0
8484

8585
- name: Set up Go
86-
uses: actions/setup-go@v5
86+
uses: actions/setup-go@v6
8787
with:
8888
go-version-file: 'go.mod'
8989
cache: true
9090

9191
- name: Build registry-builder
9292
run: go build -o registry-builder ./cmd/registry-builder
9393

94-
- name: Build registry.json
94+
- name: Build registry files (both formats)
9595
run: |
9696
mkdir -p dist
97-
./registry-builder build -v
97+
./registry-builder build --format all -v
9898
cp build/registry.json dist/registry.json
99+
cp build/official-registry.json dist/official-registry.json
99100
CONTAINER_COUNT=$(jq '.servers | length' dist/registry.json)
100101
REMOTE_COUNT=$(jq '.remote_servers | length // 0' dist/registry.json)
101102
TOTAL_COUNT=$((CONTAINER_COUNT + REMOTE_COUNT))
102103
echo "Registry built successfully with $TOTAL_COUNT entries ($CONTAINER_COUNT container-based, $REMOTE_COUNT remote)"
104+
echo "Both ToolHive and official MCP formats generated"
103105
104-
- name: Validate JSON
106+
- name: Validate JSON files
105107
run: |
108+
echo "Validating ToolHive format..."
106109
# Validate JSON structure
107110
jq empty dist/registry.json
108111
echo "✅ Valid JSON"
@@ -119,6 +122,35 @@ jobs:
119122
120123
jq -e '."$schema"' dist/registry.json > /dev/null
121124
echo "✅ Has schema field"
125+
126+
echo ""
127+
echo "Validating Official MCP format..."
128+
# Validate official registry JSON structure
129+
jq empty dist/official-registry.json
130+
echo "✅ Valid JSON"
131+
132+
# Check required fields for official format
133+
jq -e '.version' dist/official-registry.json > /dev/null
134+
echo "✅ Has version field"
135+
136+
jq -e '.meta.last_updated' dist/official-registry.json > /dev/null
137+
echo "✅ Has meta.last_updated field"
138+
139+
jq -e '.data.servers' dist/official-registry.json > /dev/null
140+
echo "✅ Has data.servers field"
141+
142+
# Check that servers have the flattened structure with _meta
143+
SERVER_COUNT=$(jq '.data.servers | length' dist/official-registry.json)
144+
if [ "$SERVER_COUNT" -gt 0 ]; then
145+
jq -e '.data.servers[0].name' dist/official-registry.json > /dev/null
146+
echo "✅ Servers have name field"
147+
148+
jq -e '.data.servers[0]._meta.publisher' dist/official-registry.json > /dev/null
149+
echo "✅ Servers have _meta.publisher field"
150+
151+
jq -e '.data.servers[0]._meta."io.modelcontextprotocol.registry"' dist/official-registry.json > /dev/null
152+
echo "✅ Servers have registry extensions"
153+
fi
122154
123155
- name: Generate metadata
124156
id: metadata
@@ -175,11 +207,15 @@ jobs:
175207
cd dist
176208
sha256sum registry.json > registry.json.sha256
177209
md5sum registry.json > registry.json.md5
210+
sha256sum official-registry.json > official-registry.json.sha256
211+
md5sum official-registry.json > official-registry.json.md5
178212
179213
- name: Create tarball
180214
run: |
181215
cd dist
182-
tar -czf registry-${{ steps.metadata.outputs.version }}.tar.gz registry.json registry.json.sha256 registry.json.md5
216+
tar -czf registry-${{ steps.metadata.outputs.version }}.tar.gz \
217+
registry.json registry.json.sha256 registry.json.md5 \
218+
official-registry.json official-registry.json.sha256 official-registry.json.md5
183219
tar -tzf registry-${{ steps.metadata.outputs.version }}.tar.gz
184220
185221
- name: Check if release exists
@@ -251,16 +287,22 @@ jobs:
251287
252288
### 📥 Download Options
253289
254-
- **registry.json** - The complete registry file
255-
- **registry-${{ steps.metadata.outputs.version }}.tar.gz** - Archive with checksums
290+
**Individual Files:**
291+
- **registry.json** - ToolHive format registry file
292+
- **official-registry.json** - Official MCP format registry file
293+
294+
**Archives:**
295+
- **registry-${{ steps.metadata.outputs.version }}.tar.gz** - Complete archive with both formats and checksums
256296
257297
### 🔗 Direct URLs
258298
259-
Latest registry is always available at:
260-
- `https://github.com/stacklok/toolhive-registry/releases/latest/download/registry.json`
299+
**ToolHive Format:**
300+
- Latest: `https://github.com/stacklok/toolhive-registry/releases/latest/download/registry.json`
301+
- This version: `https://github.com/stacklok/toolhive-registry/releases/download/v${{ steps.metadata.outputs.version }}/registry.json`
261302
262-
This specific version:
263-
- `https://github.com/stacklok/toolhive-registry/releases/download/v${{ steps.metadata.outputs.version }}/registry.json`
303+
**Official MCP Format:**
304+
- Latest: `https://github.com/stacklok/toolhive-registry/releases/latest/download/official-registry.json`
305+
- This version: `https://github.com/stacklok/toolhive-registry/releases/download/v${{ steps.metadata.outputs.version }}/official-registry.json`
264306
265307
### 📝 Recent Changes
266308
@@ -272,6 +314,9 @@ jobs:
272314
dist/registry.json
273315
dist/registry.json.sha256
274316
dist/registry.json.md5
317+
dist/official-registry.json
318+
dist/official-registry.json.sha256
319+
dist/official-registry.json.md5
275320
dist/registry-${{ steps.metadata.outputs.version }}.tar.gz
276321
makeLatest: true
277322
artifactErrorsFailBuild: true
@@ -285,13 +330,19 @@ jobs:
285330
gh release delete-asset "v${{ steps.metadata.outputs.version }}" registry.json --yes || true
286331
gh release delete-asset "v${{ steps.metadata.outputs.version }}" registry.json.sha256 --yes || true
287332
gh release delete-asset "v${{ steps.metadata.outputs.version }}" registry.json.md5 --yes || true
333+
gh release delete-asset "v${{ steps.metadata.outputs.version }}" official-registry.json --yes || true
334+
gh release delete-asset "v${{ steps.metadata.outputs.version }}" official-registry.json.sha256 --yes || true
335+
gh release delete-asset "v${{ steps.metadata.outputs.version }}" official-registry.json.md5 --yes || true
288336
gh release delete-asset "v${{ steps.metadata.outputs.version }}" "registry-${{ steps.metadata.outputs.version }}.tar.gz" --yes || true
289337
290338
# Upload new assets
291339
gh release upload "v${{ steps.metadata.outputs.version }}" \
292340
dist/registry.json \
293341
dist/registry.json.sha256 \
294342
dist/registry.json.md5 \
343+
dist/official-registry.json \
344+
dist/official-registry.json.sha256 \
345+
dist/official-registry.json.md5 \
295346
"dist/registry-${{ steps.metadata.outputs.version }}.tar.gz" \
296347
--clobber
297348
@@ -308,7 +359,7 @@ jobs:
308359
uses: actions/checkout@v5
309360

310361
- name: Set up Go
311-
uses: actions/setup-go@v5
362+
uses: actions/setup-go@v6
312363
with:
313364
go-version-file: 'go.mod'
314365
cache: true

.github/workflows/update-metadata.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
token: ${{ secrets.GITHUB_TOKEN }}
2828

2929
- name: Set up Go
30-
uses: actions/setup-go@v5
30+
uses: actions/setup-go@v6
3131
with:
3232
go-version-file: 'go.mod'
3333
cache: true

.github/workflows/update-tools.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ jobs:
125125
ref: ${{ github.head_ref || github.ref }}
126126

127127
- name: Set up Go
128-
uses: actions/setup-go@v5
128+
uses: actions/setup-go@v6
129129
with:
130130
go-version-file: 'go.mod'
131131
cache: true
@@ -295,7 +295,7 @@ jobs:
295295
ref: ${{ github.head_ref || github.ref }}
296296

297297
- name: Set up Go
298-
uses: actions/setup-go@v5
298+
uses: actions/setup-go@v6
299299
with:
300300
go-version-file: 'go.mod'
301301
cache: true

Taskfile.yml

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,41 @@ tasks:
152152
- ./{{.BUILD_DIR}}/registry-builder list -v
153153

154154
build:registry:
155-
desc: Build the registry JSON from YAML files
155+
desc: Build registry files in both ToolHive and official MCP formats
156156
deps: [build:registry-builder]
157157
cmds:
158-
- echo "🏗️ Building registry.json..."
159-
- ./{{.BUILD_DIR}}/registry-builder build -v
158+
- echo "🏗️ Building registry files (both formats)..."
159+
- ./{{.BUILD_DIR}}/registry-builder build --format all -v
160160
sources:
161161
- "{{.REGISTRY_DIR}}/**/*.yaml"
162162
- "{{.REGISTRY_DIR}}/**/*.yml"
163163
generates:
164164
- "{{.BUILD_DIR}}/registry.json"
165+
- "{{.BUILD_DIR}}/official-registry.json"
166+
167+
build:registry:toolhive:
168+
desc: Build registry in ToolHive format only
169+
deps: [build:registry-builder]
170+
cmds:
171+
- echo "🏗️ Building ToolHive registry.json..."
172+
- ./{{.BUILD_DIR}}/registry-builder build --format toolhive -v
173+
sources:
174+
- "{{.REGISTRY_DIR}}/**/*.yaml"
175+
- "{{.REGISTRY_DIR}}/**/*.yml"
176+
generates:
177+
- "{{.BUILD_DIR}}/registry.json"
178+
179+
build:registry:official:
180+
desc: Build registry in official MCP format only
181+
deps: [build:registry-builder]
182+
cmds:
183+
- echo "🏗️ Building official MCP registry..."
184+
- ./{{.BUILD_DIR}}/registry-builder build --format official-mcp-registry -v
185+
sources:
186+
- "{{.REGISTRY_DIR}}/**/*.yaml"
187+
- "{{.REGISTRY_DIR}}/**/*.yml"
188+
generates:
189+
- "{{.BUILD_DIR}}/official-registry.json"
165190

166191
test:
167192
desc: Run tests
@@ -212,7 +237,9 @@ tasks:
212237
- task: validate
213238
- task: build:registry
214239
- echo "✨ Full cycle complete!"
215-
- 'echo "Registry JSON available at: {{.BUILD_DIR}}/registry.json"'
240+
- 'echo "Registry files available at:"'
241+
- 'echo " - ToolHive format: {{.BUILD_DIR}}/registry.json"'
242+
- 'echo " - Official MCP format: {{.BUILD_DIR}}/official-registry.json"'
216243

217244
quick-start:
218245
desc: Quick start for new users
@@ -225,7 +252,7 @@ tasks:
225252
- 'echo " 1. Review imported entries in {{.REGISTRY_DIR}}/"'
226253
- echo " 2. Add new entries by creating directories with spec.yaml files"
227254
- echo " 3. Run 'task validate' to check your changes"
228-
- echo " 4. Run 'task build:registry' to generate the final JSON"
255+
- echo " 4. Run 'task build:registry' to generate registry files (both formats)"
229256

230257
version:
231258
desc: Show version information

cmd/registry-builder/main.go

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ import (
1414
"github.com/stacklok/toolhive-registry/pkg/types"
1515
)
1616

17+
const (
18+
RegistryToolHiveFormat = "toolhive"
19+
RegistryOfficialMCPRegistry = "official-mcp-registry"
20+
RegistryAllFormats = "all"
21+
)
22+
1723
var (
1824
// Version information (set during build)
1925
version = "dev"
@@ -80,7 +86,8 @@ func init() {
8086

8187
// Build command flags
8288
buildCmd.Flags().StringVarP(&outputDir, "output-dir", "o", "build", "Output directory for built registry files")
83-
buildCmd.Flags().StringVarP(&outputFormat, "format", "f", "toolhive", "Output format (toolhive, mcp-registry, all)")
89+
buildCmd.Flags().StringVarP(&outputFormat, "format", "f", "toolhive",
90+
fmt.Sprintf("Output format (%s, %s, %s)", RegistryToolHiveFormat, RegistryOfficialMCPRegistry, RegistryAllFormats))
8491

8592
// Add commands
8693
rootCmd.AddCommand(buildCmd)
@@ -150,34 +157,52 @@ func runBuild(_ *cobra.Command, _ []string) error {
150157

151158
func determineFormats(format string) []string {
152159
switch strings.ToLower(format) {
153-
case "all":
160+
case RegistryAllFormats:
154161
// Return all supported formats
155-
// For now, just toolhive, but will expand to include mcp-registry
156-
return []string{"toolhive"}
157-
case "mcp-registry", "mcp":
158-
// Future: Upstream MCP Registry format
159-
fmt.Println("Note: MCP Registry format support is planned for a future release")
160-
fmt.Println("This will generate output compatible with https://github.com/modelcontextprotocol/registry")
161-
return []string{}
162-
case "toolhive":
163-
fallthrough
162+
return []string{RegistryToolHiveFormat, RegistryOfficialMCPRegistry}
163+
case RegistryOfficialMCPRegistry:
164+
return []string{RegistryOfficialMCPRegistry}
165+
case RegistryToolHiveFormat:
166+
return []string{RegistryToolHiveFormat}
164167
default:
165-
return []string{"toolhive"}
168+
return []string{RegistryToolHiveFormat}
166169
}
167170
}
168171

169172
func buildFormat(loader *registry.Loader, format string, outputDir string) error {
170173
switch format {
171-
case "toolhive":
174+
case RegistryToolHiveFormat:
172175
return buildToolhiveFormat(loader, outputDir)
173-
case "mcp-registry":
174-
// Future implementation
175-
return fmt.Errorf("MCP Registry format not yet implemented")
176+
case RegistryOfficialMCPRegistry:
177+
return buildOfficialMCPRegistryFormat(loader, outputDir)
176178
default:
177179
return fmt.Errorf("unknown format: %s", format)
178180
}
179181
}
180182

183+
func buildOfficialMCPRegistryFormat(loader *registry.Loader, outputDir string) error {
184+
// Create official MCP Registry builder
185+
r := registry.NewOfficialRegistry(loader)
186+
187+
// Ensure output directory exists
188+
if err := os.MkdirAll(outputDir, 0750); err != nil {
189+
return fmt.Errorf("failed to create output directory: %w", err)
190+
}
191+
192+
// TODO: Add validation step
193+
194+
// Write JSON output
195+
outputPath := filepath.Join(outputDir, "official-registry.json")
196+
if err := r.WriteJSON(outputPath); err != nil {
197+
return fmt.Errorf("failed to write output: %w", err)
198+
}
199+
200+
if verbose {
201+
log.Printf("Written Official MCP Registry format to %s", outputPath)
202+
}
203+
return nil
204+
}
205+
181206
func buildToolhiveFormat(loader *registry.Loader, outputDir string) error {
182207
// Create builder
183208
builder := registry.NewBuilder(loader)
@@ -205,14 +230,6 @@ func buildToolhiveFormat(loader *registry.Loader, outputDir string) error {
205230
return nil
206231
}
207232

208-
// Future: buildMCPRegistryFormat function will be added here
209-
// func buildMCPRegistryFormat(loader *registry.Loader, outputDir string) error {
210-
// // Implementation for upstream MCP Registry format
211-
// // This will create output compatible with the MCP Registry service:
212-
// // https://github.com/modelcontextprotocol/registry
213-
// // The format will evolve as the upstream standard evolves
214-
// }
215-
216233
func runValidate(_ *cobra.Command, _ []string) error {
217234
if verbose {
218235
log.Printf("Validating registry entries in %s", registryPath)
@@ -327,15 +344,15 @@ func displayEntry(entry *types.RegistryEntry, verbose bool) {
327344
func getEntryStatus(entry *types.RegistryEntry) string {
328345
status := entry.GetStatus()
329346
if status == "" {
330-
status = "Active"
347+
status = types.StatusActive
331348
}
332349
return status
333350
}
334351

335352
func getEntryTier(entry *types.RegistryEntry) string {
336353
tier := entry.GetTier()
337354
if tier == "" {
338-
tier = "Community"
355+
tier = types.TierCommunity
339356
}
340357
return tier
341358
}

0 commit comments

Comments
 (0)