Stack featured icon data on catalog icon tooling · github/agentfinder-catalog@92a142d · GitHub
Skip to content

Commit 92a142d

Browse files
aphansal123Copilot
andcommitted
Stack featured icon data on catalog icon tooling
Preserve approved data while using the icon-aware generator in CI. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b21c356f-7fbf-4392-8f95-f5c987dba212
2 parents 444fdc7 + 23b8785 commit 92a142d

8 files changed

Lines changed: 796 additions & 13 deletions

File tree

‎.github/workflows/catalog.yml‎

Lines changed: 6 additions & 0 deletions

‎CONTRIBUTING.md‎

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,156 @@ Do not create a copied descriptor to represent a server that is already imported
8282
Registry references do not identify a file in this repository. Do not attach
8383
`metadata.sourceSet` or `metadata.repoPath` pointing to a copied descriptor.
8484

85+
#### Reviewed resource icons
86+
87+
Icons are optional. Declare them in the root `catalog-icons.json` overlay, for
88+
both contributor-managed and registry-imported resources. Do not copy a registry
89+
descriptor or create another resource entry to attach an icon. Use the exact
90+
generated `urn:air:` identifier from `ai-catalog.json`, not the source `urn:ai:`
91+
identifier, a display name, or a descriptor URL.
92+
93+
The tooling-only overlay is empty; artwork and production declarations are
94+
reviewed in a separate change.
95+
The following is a **synthetic example**, not an available asset, real digest,
96+
or evidence of permission:
97+
98+
```json
99+
{
100+
"icons": [
101+
{
102+
"identifier": "urn:air:registry.modelcontextprotocol.io:example:weather",
103+
"url": "https://raw.githubusercontent.com/github/agentfinder-catalog/0123456789abcdef0123456789abcdef01234567/icons/example/weather.png",
104+
"provenance": {
105+
"sourceUrl": "https://example.com/weather-artwork",
106+
"license": "CC0-1.0",
107+
"permissionUrl": "https://example.com/weather-artwork-permission",
108+
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
109+
}
110+
}
111+
]
112+
}
113+
```
114+
115+
Omit `version` to cover all versions of that exact identifier. To restrict an
116+
icon to one existing version, add a nonempty `version` string to the declaration.
117+
Do not supply `null`. Duplicate or overlapping declarations fail validation,
118+
including an identifier-wide declaration combined with an exact-version one.
119+
Unmatched identifiers or versions also fail; explicitly maintain declarations
120+
when a registry resource disappears or a version-specific reference rolls over.
121+
Prefer identifier-wide declarations when the artwork legitimately covers all
122+
versions.
123+
124+
The generator applies the overlay after normal entry selection and registry
125+
imports, adding only the scalar
126+
`metadata["com.github.agentfinder.icon.url"]`. It preserves identifiers, versions,
127+
descriptor URLs, native data, and other metadata. Provenance is not published in
128+
the generated entry. The icon key is reserved for the overlay: do not put it
129+
directly in contributor-managed entries or registry inputs. Unknown overlay
130+
fields and duplicate JSON keys are rejected. An absent overlay is treated as
131+
empty for compatibility with older checkouts.
132+
133+
For the example above, the generated entry is:
134+
135+
```json
136+
{
137+
"identifier": "urn:air:registry.modelcontextprotocol.io:example:weather",
138+
"displayName": "Weather",
139+
"type": "application/mcp-server+json",
140+
"version": "1.0.0",
141+
"url": "https://api.mcp.github.com/v0.1/servers/example%2Fweather/versions/1.0.0",
142+
"metadata": {
143+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/0123456789abcdef0123456789abcdef01234567/icons/example/weather.png"
144+
}
145+
}
146+
```
147+
148+
This input key is not a new client response field. Once service support is
149+
deployed, Agent Finder emits the optional nested `metadata.github.icon.url`.
150+
A supported curated URL takes precedence over a supported descriptor-declared
151+
icon. Removing the curated declaration restores descriptor-icon fallback;
152+
it does not suppress a descriptor icon. Invalid service-side declarations also
153+
fall back. Invalid catalog-authored declarations instead fail generation.
154+
Clients keep their resource-type fallback when no supported icon is available
155+
or an image cannot be loaded.
156+
157+
##### Asset review and validation
158+
159+
- Place reviewed assets at `icons/<publisher>/<asset>.png`. Publisher and asset
160+
names start with an ASCII letter, digit, underscore, or hyphen; remaining
161+
characters may also include dots. Asset paths cannot contain symlinks.
162+
- Use **static PNG** files, at most **256 KiB (262144 bytes)**, with width and
163+
height between **1 and 512 pixels**. Pillow verifies PNG integrity and decodes
164+
the image; animated images are rejected. Validation follows Pillow's PNG
165+
decoder rather than implementing a separate strict chunk grammar (for example,
166+
it does not reject otherwise decodable PNGs solely for trailing bytes).
167+
These checks are not image sanitization; reviewers must inspect the rendered image.
168+
- URLs must use HTTPS and the exact `raw.githubusercontent.com` host, this
169+
repository, a full lowercase 40-hex commit reference, and the asset path.
170+
Mutable refs, credentials, explicit ports, query strings, fragments, encoded
171+
paths, other hosts/repositories, and other image formats are rejected.
172+
- Supply `sourceUrl` identifying the original artwork, `license` identifying its
173+
license or explicit permission, `permissionUrl` pointing to reviewable evidence
174+
that redistribution of these bytes is permitted, and a lowercase `sha256` of
175+
the actual file. Alternatively, when approval is given without a URL, supply
176+
`sourceUrl`, `sha256`, and a nonempty `approval` attestation describing the
177+
explicit authorization for public redistribution; do not invent a license or
178+
permission link. These two provenance forms are mutually exclusive.
179+
Source and permission URLs must be absolute HTTPS without
180+
credentials or ports. Generator checks establish syntax and a matching local
181+
digest, **not legal permission, public availability, or ownership**. Reviewers
182+
must verify the evidence and any attribution or notice requirements.
183+
- Do not infer logos from repository-owner avatars or acquire/copy vendor artwork
184+
without verified redistribution permission. The repository's MIT license
185+
does not establish permission for third-party artwork. An icon does not prove
186+
vendor ownership, endorsement, or official-product approval.
187+
188+
Compute a file's digest with:
189+
190+
```bash
191+
shasum -a 256 icons/<publisher>/<asset>.png
192+
```
193+
194+
##### Adding, replacing, and removing icons
195+
196+
**Add:** obtain permission and fulfill any required notices first. Publish the
197+
reviewed asset in an asset-only commit, then use that existing commit's raw URL
198+
in a separate declaration change. A declaration cannot pin the SHA of its own
199+
containing commit. Reviewers must fetch the public pinned URL and verify its bytes
200+
against the recorded SHA-256: the generator checks the file in the current
201+
checkout, not the remote asset at that commit. Regenerate and review
202+
`ai-catalog.json`; only the intended icon metadata should change.
203+
204+
**Replace:** publish the newly reviewed asset first, then update its immutable URL,
205+
provenance, and digest together. Changed image bytes must have a changed URL.
206+
Do not merely overwrite an asset while retaining an old pinned URL. If different
207+
resource versions need different bytes, use distinct paths so all declared assets
208+
can be checked in the current tree.
209+
210+
**Remove:** remove the overlay record and regenerate. Delete an unused current
211+
asset only after removing all declarations that reference it. Historical pinned
212+
bytes remain retrievable; deleting the current file does not revoke old URLs.
213+
The service owner handles enrichment invalidation and reconciliation so an
214+
addition, replacement, or removal takes effect in responses.
215+
216+
Validate icon changes with the normal generation commands below and:
217+
218+
```bash
219+
python3 -m unittest discover -s tests
220+
```
221+
222+
Tooling may land before service support only if the empty overlay leaves generated
223+
resources unchanged. **Production declaration publication must follow deployed
224+
github/agentfinder#557 foundation and github/copilot-ecosystem#1625 service
225+
support**, plus verified redistribution permission. Catalog tooling alone is
226+
not end-to-end icon delivery.
227+
228+
The current ARD specification is
229+
[v0.91 (Proposal)](https://github.com/ards-project/ard-spec/blob/49eb4df6f3841ccecc5c31d5175117337b568bdf/spec/ard.md);
230+
the catalog envelope remains `specVersion: "1.0"`. Both current entry and catalog
231+
schemas permit scalar metadata extensions, which is why this declaration is flat.
232+
This change does not adopt JSON-LD contexts or imply support for every behavior
233+
in the latest proposal.
234+
85235
#### Canvas-only plugins
86236

87237
Catalog entries for plugins whose functionality consists entirely of a GitHub Copilot
@@ -108,6 +258,7 @@ Make sure your file is valid JSON, then regenerate and check the ARD ingestion c
108258

109259
```bash
110260
python -m json.tool catalog/<your-publisher>/<augment-name>.json
261+
python3 -m pip install -r requirements.txt
111262
python3 scripts/generate_ai_catalog.py
112263
python3 scripts/generate_ai_catalog.py --check
113264
```

‎README.md‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,37 @@ Each augment is a single JSON file under the publisher's directory. The publishe
2828

2929
These per-entry files are the source of truth for contributor-managed entries. The root `ai-catalog.json` is a generated Agentic Resource Discovery (ARD) ingestion artifact that also includes missing entries from GitHub's public MCP catalog. Do not edit it by hand; regenerate it with `python3 scripts/generate_ai_catalog.py`.
3030

31+
Install the generator's image-validation dependency first with
32+
`python3 -m pip install -r requirements.txt` (preferably in a virtual environment).
33+
3134
The Catalog workflow checks the [GitHub MCP Registry](https://api.mcp.github.com/.well-known/ai-catalog.json) hourly, independently of repository changes, and opens or updates the `automation/update-ai-catalog` pull request when the generated catalog changes. This refresh picks up registry additions and current server-version references; it does not query the general public MCP registry. Refresh changes still require the pull request to be merged before they reach the main-branch catalog. GitHub Actions schedules can be delayed, and a manual workflow run on `main` uses the same publication flow.
3235

36+
## Optional reviewed icons
37+
38+
`catalog-icons.json` is an identity-keyed overlay for both local and
39+
registry-imported resources. This tooling-only change leaves it empty; artwork
40+
and production declarations are reviewed separately.
41+
Declarations use the existing generated `urn:air:` identifier
42+
and optional exact version, without duplicating resources or changing descriptor
43+
URLs. Generation adds only the scalar `metadata["com.github.agentfinder.icon.url"]`;
44+
source provenance stays in the overlay.
45+
46+
Reviewed assets belong under `icons/<publisher>/<asset>.png`, with recorded
47+
redistribution permission or an explicit approval attestation, a matching SHA-256,
48+
and immutable commit-pinned HTTPS
49+
`raw.githubusercontent.com` URLs. Initial validation permits static PNG files up
50+
to 256 KiB and 512 by 512 pixels. See
51+
[the icon contribution guide](CONTRIBUTING.md#reviewed-resource-icons) for exact
52+
fixtures, validation, and addition/replacement/removal instructions. Icons imply
53+
neither endorsement nor official-product ownership.
54+
55+
Production publication of declarations follows deployed
56+
[github/agentfinder#557](https://github.com/github/agentfinder/pull/557) and
57+
[github/copilot-ecosystem#1625](https://github.com/github/copilot-ecosystem/issues/1625)
58+
service support. Clients continue using optional `metadata.github.icon.url` and
59+
their existing fallbacks. Catalog validation does not mean the service fetches or
60+
validates image bytes.
61+
3362
## Contributing
3463

3564
Want to list your skill or MCP server in the catalog? See **[CONTRIBUTING.md](CONTRIBUTING.md)** for the full guide, including the JSON schema, validation steps, and PR process.

‎ai-catalog.json‎

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,7 +2129,8 @@
21292129
],
21302130
"metadata": {
21312131
"sourceSet": "atlassian-labs/copilot-marketplace",
2132-
"repoPath": ".claude-plugin/plugin.json"
2132+
"repoPath": ".claude-plugin/plugin.json",
2133+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/atlassian-labs/jira.png"
21332134
},
21342135
"type": "application/vnd.anthropic.claude-plugin+json"
21352136
},
@@ -10817,7 +10818,8 @@
1081710818
],
1081810819
"metadata": {
1081910820
"sourceSet": "github/awesome-copilot",
10820-
"repoPath": "plugins/security-best-practices/plugin.json"
10821+
"repoPath": "plugins/security-best-practices/plugin.json",
10822+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/github/security-best-practices.png"
1082110823
},
1082210824
"type": "application/vnd.github.copilot-plugin"
1082310825
},
@@ -10858,7 +10860,8 @@
1085810860
],
1085910861
"metadata": {
1086010862
"sourceSet": "github/awesome-copilot",
10861-
"repoPath": "plugins/sentry-triage/plugin.json"
10863+
"repoPath": "plugins/sentry-triage/plugin.json",
10864+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/sentry/sentry-triage.png"
1086210865
},
1086310866
"type": "application/vnd.github.copilot-plugin"
1086410867
},
@@ -15429,7 +15432,8 @@
1542915432
"description": "A relentless interview to sharpen a plan or design.",
1543015433
"metadata": {
1543115434
"sourceSet": "mattpocock/skills",
15432-
"repoPath": "skills/productivity/grill-me/SKILL.md"
15435+
"repoPath": "skills/productivity/grill-me/SKILL.md",
15436+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/mattpocock/grill-me.png"
1543315437
},
1543415438
"type": "application/ai-skill"
1543515439
},
@@ -15453,7 +15457,8 @@
1545315457
"description": "Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.",
1545415458
"metadata": {
1545515459
"sourceSet": "mattpocock/skills",
15456-
"repoPath": "skills/productivity/grilling/SKILL.md"
15460+
"repoPath": "skills/productivity/grilling/SKILL.md",
15461+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/mattpocock/grill-me.png"
1545715462
},
1545815463
"type": "application/ai-skill"
1545915464
},
@@ -16622,7 +16627,8 @@
1662216627
],
1662316628
"metadata": {
1662416629
"sourceSet": "microsoft/azure-devops-copilot-plugin",
16625-
"repoPath": ".claude-plugin/plugin.json"
16630+
"repoPath": ".claude-plugin/plugin.json",
16631+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/microsoft/azure-devops.png"
1662616632
},
1662716633
"type": "application/vnd.anthropic.claude-plugin+json"
1662816634
},
@@ -17240,7 +17246,8 @@
1724017246
],
1724117247
"metadata": {
1724217248
"sourceSet": "microsoft/azure-skills",
17243-
"repoPath": ".github/plugins/azure-skills/.plugin/plugin.json"
17249+
"repoPath": ".github/plugins/azure-skills/.plugin/plugin.json",
17250+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/microsoft/azure.png"
1724417251
},
1724517252
"type": "application/vnd.github.copilot-plugin"
1724617253
},
@@ -18085,7 +18092,8 @@
1808518092
],
1808618093
"metadata": {
1808718094
"sourceSet": "microsoft/foundry-dev-tools",
18088-
"repoPath": "microsoft-foundry/plugin.json"
18095+
"repoPath": "microsoft-foundry/plugin.json",
18096+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/microsoft/microsoft-foundry.png"
1808918097
},
1809018098
"type": "application/vnd.github.copilot-plugin"
1809118099
},
@@ -18481,7 +18489,8 @@
1848118489
"description": "Query Microsoft 365 data with natural language - emails, meetings, documents, Teams messages, and more.",
1848218490
"metadata": {
1848318491
"sourceSet": "microsoft/work-iq",
18484-
"repoPath": "plugins/workiq/.github/plugin/plugin.json"
18492+
"repoPath": "plugins/workiq/.github/plugin/plugin.json",
18493+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/microsoft/workiq.png"
1848518494
},
1848618495
"type": "application/vnd.github.copilot-plugin"
1848718496
},
@@ -19769,7 +19778,8 @@
1976919778
],
1977019779
"metadata": {
1977119780
"sourceSet": "pbakaus/impeccable",
19772-
"repoPath": "plugin/skills/impeccable/SKILL.md"
19781+
"repoPath": "plugin/skills/impeccable/SKILL.md",
19782+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/pbakaus/impeccable.png"
1977319783
},
1977419784
"type": "application/ai-skill"
1977519785
},
@@ -24291,7 +24301,8 @@
2429124301
"readmeUrl": "https://github.com/figma/mcp-server-guide#readme",
2429224302
"repository": "https://github.com/figma/mcp-server-guide",
2429324303
"repositorySource": "github",
24294-
"stargazerCount": 2070
24304+
"stargazerCount": 2070,
24305+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/figma/figma.png"
2429524306
}
2429624307
},
2429724308
{
@@ -31922,7 +31933,8 @@
3192231933
"readmeUrl": "https://github.com/microsoft/azure-devops-mcp#readme",
3192331934
"repository": "https://github.com/microsoft/azure-devops-mcp",
3192431935
"repositorySource": "github",
31925-
"stargazerCount": 2054
31936+
"stargazerCount": 2054,
31937+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/microsoft/azure-devops.png"
3192631938
}
3192731939
},
3192831940
{
@@ -32018,7 +32030,8 @@
3201832030
"readmeUrl": "https://github.com/microsoft/playwright-mcp#readme",
3201932031
"repository": "https://github.com/microsoft/playwright-mcp",
3202032032
"repositorySource": "github",
32021-
"stargazerCount": 38104
32033+
"stargazerCount": 38104,
32034+
"com.github.agentfinder.icon.url": "https://raw.githubusercontent.com/github/agentfinder-catalog/08dc319501a58ca849999e2b7cc1d34225e13d3a/icons/microsoft/playwright.png"
3202232035
}
3202332036
},
3202432037
{

‎requirements.txt‎

Lines changed: 1 addition & 0 deletions

0 commit comments

Comments
 (0)