Skip to content

Commit 3e30214

Browse files
Add official vendors registry (#887)
* Bootstrap an official-only catalog Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com> * Ingest the initial list of official MCP servers Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com> * chore: update tool lists for MCP servers (server.json)\n\nUpdated servers:\n- aws-diagram\n- aws-pricing\n- browserbase\n- buildkite\n- chroma-mcp\n- chrome-devtools-mcp\n- cloud-run\n- firecrawl\n- github\n- graphlit\n- kyverno\n- mcp-clickhouse\n- mcp-server-circleci\n- notion\n- pagerduty\n- phoenix\n- playwright\n- redhat-linux\n- redis\n- semgrep\n- sentry\n- stripe\n- supabase\n- terraform\n\nAutomatically updated using 'catalog update-tools' command.\n\nCo-authored-by: rdimitrov <rdimitrov@users.noreply.github.com> --------- Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com> Co-authored-by: GitHub Action <action@github.com>
1 parent ec2e0a6 commit 3e30214

File tree

138 files changed

+106949
-86
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

138 files changed

+106949
-86
lines changed

.github/workflows/ci.yml

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,26 @@ jobs:
135135
if [ -n "$EXISTING_PR" ]; then
136136
echo "PR #$EXISTING_PR already exists, updated branch"
137137
else
138+
# Build file list dynamically
139+
FILE_LIST=""
140+
for registry_dir in pkg/catalog/*/; do
141+
registry_name=$(basename "$registry_dir")
142+
[ -d "$registry_dir/data" ] || continue
143+
FILE_LIST="${FILE_LIST}- \`pkg/catalog/${registry_name}/data/registry.json\` — ${registry_name} legacy format
144+
"
145+
FILE_LIST="${FILE_LIST}- \`pkg/catalog/${registry_name}/data/official-registry.json\` — ${registry_name} upstream MCP format
146+
"
147+
done
148+
138149
gh pr create \
139150
--title "chore: update catalog data files for v${VERSION}" \
140-
--body "$(cat <<'BODY'
151+
--body "$(cat <<EOF
141152
Automated PR to update the embedded catalog data files.
142153
143154
Files updated:
144-
- `pkg/catalog/toolhive/data/registry.json` — ToolHive legacy format
145-
- `pkg/catalog/toolhive/data/official-registry.json` — Upstream MCP format
146-
155+
${FILE_LIST}
147156
When merged, a release will be created automatically.
148-
BODY
157+
EOF
149158
)" \
150159
--head "$BRANCH"
151160
@@ -182,25 +191,35 @@ jobs:
182191
- name: Generate PR comment
183192
id: comment
184193
run: |
185-
CONTAINER_COUNT=$(jq '.servers | length' build/toolhive/registry.json)
186-
REMOTE_COUNT=$(jq '.remote_servers | length // 0' build/toolhive/registry.json)
187-
TOTAL=$((CONTAINER_COUNT + REMOTE_COUNT))
188-
SKILL_COUNT=$(jq '.data.skills | length // 0' build/toolhive/official-registry.json)
189-
SIZE=$(du -h build/toolhive/registry.json | cut -f1)
190-
LAST_UPDATED=$(jq -r '.last_updated' build/toolhive/registry.json)
191-
192194
{
193195
echo "body<<EOF"
194196
echo "## Registry Build Preview"
195197
echo ""
196-
echo "Registry built successfully!"
198+
echo "All registries built successfully!"
197199
echo ""
198-
echo "- **Total Servers**: $TOTAL"
199-
echo " - Container-based: $CONTAINER_COUNT"
200-
echo " - Remote: $REMOTE_COUNT"
201-
echo "- **Skills**: $SKILL_COUNT"
202-
echo "- **File Size**: $SIZE"
203-
echo "- **Last Updated**: $LAST_UPDATED"
200+
201+
for registry_dir in build/*/; do
202+
registry_name=$(basename "$registry_dir")
203+
[ -f "$registry_dir/registry.json" ] || continue
204+
205+
CONTAINER_COUNT=$(jq '.servers | length' "$registry_dir/registry.json")
206+
REMOTE_COUNT=$(jq '.remote_servers | length // 0' "$registry_dir/registry.json")
207+
TOTAL=$((CONTAINER_COUNT + REMOTE_COUNT))
208+
SKILL_COUNT=$(jq '.data.skills | length // 0' "$registry_dir/official-registry.json")
209+
SIZE=$(du -h "$registry_dir/registry.json" | cut -f1)
210+
LAST_UPDATED=$(jq -r '.last_updated' "$registry_dir/registry.json")
211+
212+
echo "### Registry: \`$registry_name\`"
213+
echo ""
214+
echo "- **Total Servers**: $TOTAL"
215+
echo " - Container-based: $CONTAINER_COUNT"
216+
echo " - Remote: $REMOTE_COUNT"
217+
echo "- **Skills**: $SKILL_COUNT"
218+
echo "- **File Size**: $SIZE"
219+
echo "- **Last Updated**: $LAST_UPDATED"
220+
echo ""
221+
done
222+
204223
echo "EOF"
205224
} >> $GITHUB_OUTPUT
206225
@@ -230,6 +249,6 @@ jobs:
230249
with:
231250
name: pr-registry-json
232251
path: |
233-
build/toolhive/registry.json
234-
build/toolhive/official-registry.json
252+
build/*/registry.json
253+
build/*/official-registry.json
235254
retention-days: 7

.github/workflows/release.yml

Lines changed: 79 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -26,75 +26,94 @@ jobs:
2626
echo "version=0.$(date +'%Y%m%d').0" >> $GITHUB_OUTPUT
2727
echo "date=$(date +'%Y.%m.%d')" >> $GITHUB_OUTPUT
2828
29-
- name: Collect registry stats
30-
id: stats
29+
- name: Generate release body
30+
id: release_body
3131
run: |
32+
{
33+
echo "body<<EOF"
34+
echo "## ToolHive Catalog Release"
35+
echo ""
36+
echo "**Date**: ${{ steps.metadata.outputs.date }}"
37+
echo ""
38+
39+
for registry_dir in pkg/catalog/*/; do
40+
registry_name=$(basename "$registry_dir")
41+
data_file="$registry_dir/data/registry.json"
42+
[ -f "$data_file" ] || continue
43+
44+
CONTAINER_COUNT=$(jq '.servers | length' "$data_file")
45+
REMOTE_COUNT=$(jq '.remote_servers | length // 0' "$data_file")
46+
TOTAL=$((CONTAINER_COUNT + REMOTE_COUNT))
47+
LAST_UPDATED=$(jq -r '.last_updated' "$data_file")
48+
49+
upstream_file="$registry_dir/data/official-registry.json"
50+
if [ -f "$upstream_file" ]; then
51+
SKILL_COUNT=$(jq '.data.skills | length // 0' "$upstream_file")
52+
else
53+
SKILL_COUNT=0
54+
fi
55+
56+
echo "### Registry: \`$registry_name\`"
57+
echo ""
58+
echo "**Last Updated**: $LAST_UPDATED"
59+
echo ""
60+
echo "| Category | Count |"
61+
echo "|----------|-------|"
62+
echo "| **Total Servers** | $TOTAL |"
63+
echo "| **Container-based** | $CONTAINER_COUNT |"
64+
echo "| **Remote** | $REMOTE_COUNT |"
65+
echo "| **Skills** | $SKILL_COUNT |"
66+
echo ""
67+
echo "\`\`\`sh"
68+
echo "go get github.com/stacklok/toolhive-catalog/pkg/catalog/${registry_name}@latest"
69+
echo "\`\`\`"
70+
echo ""
71+
echo "\`\`\`go"
72+
echo "import \"github.com/stacklok/toolhive-catalog/pkg/catalog/${registry_name}\""
73+
echo ""
74+
echo "// ToolHive legacy format"
75+
echo "data := ${registry_name}.Legacy()"
76+
echo ""
77+
echo "// Upstream MCP format"
78+
echo "data := ${registry_name}.Upstream()"
79+
echo "\`\`\`"
80+
echo ""
81+
done
82+
83+
echo "---"
84+
echo "*This is an automated release triggered by a catalog data update.*"
85+
echo "EOF"
86+
} >> $GITHUB_OUTPUT
87+
88+
- name: Collect release artifacts
89+
id: artifacts
90+
run: |
91+
ARTIFACT_LIST=""
3292
for registry_dir in pkg/catalog/*/; do
33-
registry_name=$(basename "$registry_dir")
34-
data_file="$registry_dir/data/registry.json"
35-
[ -f "$data_file" ] || continue
36-
37-
CONTAINER_COUNT=$(jq '.servers | length' "$data_file")
38-
REMOTE_COUNT=$(jq '.remote_servers | length // 0' "$data_file")
39-
TOTAL=$((CONTAINER_COUNT + REMOTE_COUNT))
40-
LAST_UPDATED=$(jq -r '.last_updated' "$data_file")
41-
42-
# Count skills from the upstream format
43-
upstream_file="$registry_dir/data/official-registry.json"
44-
if [ -f "$upstream_file" ]; then
45-
SKILL_COUNT=$(jq '.data.skills | length // 0' "$upstream_file")
46-
else
47-
SKILL_COUNT=0
48-
fi
49-
50-
echo "${registry_name}_total=$TOTAL" >> $GITHUB_OUTPUT
51-
echo "${registry_name}_container=$CONTAINER_COUNT" >> $GITHUB_OUTPUT
52-
echo "${registry_name}_remote=$REMOTE_COUNT" >> $GITHUB_OUTPUT
53-
echo "${registry_name}_skills=$SKILL_COUNT" >> $GITHUB_OUTPUT
54-
echo "${registry_name}_last_updated=$LAST_UPDATED" >> $GITHUB_OUTPUT
93+
[ -d "$registry_dir/data" ] || continue
94+
for f in "$registry_dir"/data/*.json; do
95+
[ -f "$f" ] || continue
96+
if [ -n "$ARTIFACT_LIST" ]; then
97+
ARTIFACT_LIST="${ARTIFACT_LIST}
98+
${f}"
99+
else
100+
ARTIFACT_LIST="$f"
101+
fi
102+
done
55103
done
104+
{
105+
echo "files<<EOF"
106+
echo "$ARTIFACT_LIST"
107+
echo "EOF"
108+
} >> $GITHUB_OUTPUT
56109
57110
- name: Create or update release
58111
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
59112
with:
60113
tag: v${{ steps.metadata.outputs.version }}
61114
name: Catalog v${{ steps.metadata.outputs.date }}
62-
body: |
63-
## ToolHive Catalog Release
64-
65-
**Date**: ${{ steps.metadata.outputs.date }}
66-
**Last Updated**: ${{ steps.stats.outputs.toolhive_last_updated }}
67-
68-
### Statistics
69-
70-
| Category | Count |
71-
|----------|-------|
72-
| **Total Servers** | ${{ steps.stats.outputs.toolhive_total }} |
73-
| **Container-based** | ${{ steps.stats.outputs.toolhive_container }} |
74-
| **Remote** | ${{ steps.stats.outputs.toolhive_remote }} |
75-
| **Skills** | ${{ steps.stats.outputs.toolhive_skills }} |
76-
77-
### Usage
78-
79-
```sh
80-
go get github.com/stacklok/toolhive-catalog/pkg/catalog/toolhive@latest
81-
```
82-
83-
```go
84-
import "github.com/stacklok/toolhive-catalog/pkg/catalog/toolhive"
85-
86-
// ToolHive legacy format
87-
data := toolhive.Legacy()
88-
89-
// Upstream MCP format
90-
data := toolhive.Upstream()
91-
```
92-
93-
---
94-
*This is an automated release triggered by a catalog data update.*
95-
artifacts: |
96-
pkg/catalog/toolhive/data/registry.json
97-
pkg/catalog/toolhive/data/official-registry.json
115+
body: ${{ steps.release_body.outputs.body }}
116+
artifacts: ${{ steps.artifacts.outputs.files }}
98117
allowUpdates: true
99118
makeLatest: true
100119
env:

pkg/catalog/official/catalog.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Package official provides the pre-built official vendors registry as embedded bytes.
2+
//
3+
// This registry contains MCP servers and skills from official vendors,
4+
// companies, and widely popular community projects.
5+
//
6+
// The data files are updated daily by the build workflow and committed to the
7+
// repository, so the embedded content reflects the last daily build.
8+
//
9+
// Two formats are available via [Legacy] and [Upstream]:
10+
// - Legacy: ToolHive's own registry format (registry.json)
11+
// - Upstream: The upstream MCP official registry format (official-registry.json)
12+
package official
13+
14+
import _ "embed"
15+
16+
//go:embed data/registry.json
17+
var legacyRegistry []byte
18+
19+
//go:embed data/official-registry.json
20+
var upstreamRegistry []byte
21+
22+
// Legacy returns the registry in ToolHive's legacy format.
23+
func Legacy() []byte {
24+
return legacyRegistry
25+
}
26+
27+
// Upstream returns the registry in the upstream MCP official format.
28+
func Upstream() []byte {
29+
return upstreamRegistry
30+
}

0 commit comments

Comments
 (0)