Skip to content

Commit 8100ef0

Browse files
committed
Add Mintlify documentation site
- Add docs/ folder with Mintlify configuration - Add generate_mintlify_agents.py to generate agent cards from registry - Update update-versions.yml to regenerate docs on version updates - Update CLAUDE.md with documentation site instructions
1 parent cad6e09 commit 8100ef0

File tree

11 files changed

+535
-0
lines changed

11 files changed

+535
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env python3
2+
from __future__ import annotations
3+
4+
import json
5+
from pathlib import Path
6+
import re
7+
8+
ROOT = Path(__file__).resolve().parents[2]
9+
DOCS_DIR = ROOT / "docs"
10+
TEMPLATE_PATH = DOCS_DIR / "_index.mdx"
11+
OUTPUT_PATH = DOCS_DIR / "index.mdx"
12+
PLACEHOLDER = "$$AGENTS_CARDS$$"
13+
14+
15+
def _escape_html(text: str) -> str:
16+
return (
17+
text.replace("&", "&")
18+
.replace("<", "&lt;")
19+
.replace(">", "&gt;")
20+
.replace('"', "&quot;")
21+
.replace("'", "&#39;")
22+
)
23+
24+
25+
def _escape_text(text: str) -> str:
26+
return _escape_html(text).replace("\n", " ")
27+
28+
29+
def _sanitize_svg(svg: str) -> str:
30+
svg = svg.strip()
31+
svg = re.sub(r'\s(width|height)="[^"]*"', "", svg)
32+
svg = re.sub(r'\sclass="[^"]*"', "", svg)
33+
svg = re.sub(
34+
r"<svg\b",
35+
(
36+
'<svg width="20" height="20" '
37+
'className="agent-icon" '
38+
'aria-hidden="true" focusable="false"'
39+
),
40+
svg,
41+
count=1,
42+
)
43+
replacements = {
44+
"fill-rule": "fillRule",
45+
"clip-rule": "clipRule",
46+
"clip-path": "clipPath",
47+
"stroke-width": "strokeWidth",
48+
"stroke-linecap": "strokeLinecap",
49+
"stroke-linejoin": "strokeLinejoin",
50+
"stroke-miterlimit": "strokeMiterlimit",
51+
"stroke-dasharray": "strokeDasharray",
52+
"stroke-dashoffset": "strokeDashoffset",
53+
"stroke-opacity": "strokeOpacity",
54+
"fill-opacity": "fillOpacity",
55+
"stop-color": "stopColor",
56+
"stop-opacity": "stopOpacity",
57+
"vector-effect": "vectorEffect",
58+
}
59+
for old, new in replacements.items():
60+
svg = svg.replace(f"{old}=", f"{new}=")
61+
return svg
62+
63+
64+
def _load_icon_svg(agent: dict) -> str:
65+
icon_src = agent["_dir"] / "icon.svg"
66+
if not icon_src.exists():
67+
return ""
68+
return _sanitize_svg(icon_src.read_text())
69+
70+
71+
def _load_agents() -> list[dict]:
72+
agents: list[dict] = []
73+
for entry in sorted(ROOT.iterdir()):
74+
if not entry.is_dir():
75+
continue
76+
agent_file = entry / "agent.json"
77+
if not agent_file.exists():
78+
continue
79+
data = json.loads(agent_file.read_text())
80+
data["_dir"] = entry
81+
agents.append(data)
82+
agents.sort(key=lambda agent: agent.get("name", "").lower())
83+
return agents
84+
85+
86+
def _render_agent_cards(agents: list[dict]) -> str:
87+
lines: list[str] = ["<Columns cols={2}>"]
88+
89+
for agent in agents:
90+
agent_id = agent.get("id", "-")
91+
name = agent.get("name", agent_id)
92+
description = _escape_text(agent.get("description", "-"))
93+
version = _escape_text(agent.get("version", "-"))
94+
repository = agent.get("repository", "")
95+
icon_svg = _load_icon_svg(agent)
96+
97+
lines.append(" <Card")
98+
lines.append(f' title="{_escape_html(name)}"')
99+
if icon_svg:
100+
lines.append(" icon={")
101+
for line in icon_svg.splitlines():
102+
lines.append(f" {line}")
103+
lines.append(" }")
104+
if repository:
105+
lines.append(f' href="{_escape_html(repository)}"')
106+
lines.append(' arrow="true"')
107+
lines.append(" >")
108+
lines.append(f" {description}")
109+
version_text = version if version not in ("", "-") else "version unknown"
110+
lines.append(f" <p><code>{_escape_text(version_text)}</code></p>")
111+
lines.append(" </Card>")
112+
113+
lines.append("</Columns>")
114+
return "\n".join(lines)
115+
116+
117+
def main() -> None:
118+
agents = _load_agents()
119+
template = TEMPLATE_PATH.read_text()
120+
cards = _render_agent_cards(agents)
121+
output = template.replace(PLACEHOLDER, cards)
122+
OUTPUT_PATH.write_text(output)
123+
124+
125+
if __name__ == "__main__":
126+
main()

.github/workflows/update-versions.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ jobs:
143143
pip install jsonschema
144144
SKIP_URL_VALIDATION=1 python .github/workflows/build_registry.py
145145
146+
- name: Generate docs
147+
run: python .github/workflows/generate_mintlify_agents.py
148+
146149
- name: Generate commit message
147150
id: commit_msg
148151
run: |

CLAUDE.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,47 @@ Using `currentColor` enables icons to adapt to different themes (light/dark mode
110110
**Invalid patterns:**
111111
- Hardcoded colors: `fill="#FF5500"`, `fill="red"`, `stroke="rgb(0,0,0)"`
112112
- Missing currentColor: `fill` or `stroke` without `currentColor`
113+
114+
## Documentation Site
115+
116+
The registry has a documentation site built with [Mintlify](https://mintlify.com/) in the `docs/` folder.
117+
118+
### Structure
119+
120+
```
121+
docs/
122+
├── docs.json # Mintlify configuration
123+
├── _index.mdx # Template for index page (contains $$AGENTS_CARDS$$ placeholder)
124+
├── index.mdx # Generated index page with agent cards
125+
├── registry.mdx # Registry format documentation
126+
└── logo/ # Logo assets
127+
```
128+
129+
### Commands
130+
131+
```bash
132+
# Generate docs (regenerates index.mdx from template)
133+
uv run .github/workflows/generate_mintlify_agents.py
134+
135+
# Run local dev server
136+
cd docs && npx mintlify dev --port 3000
137+
```
138+
139+
### How It Works
140+
141+
1. `_index.mdx` is a template containing `$$AGENTS_CARDS$$` placeholder
142+
2. `generate_mintlify_agents.py` reads all `agent.json` files from the registry
143+
3. Generates `<Card>` components for each agent with name, description, version, and icon
144+
4. Icons are inlined as sanitized SVG (converted to JSX-compatible attributes)
145+
5. Replaces placeholder and writes to `index.mdx`
146+
147+
### Automation
148+
149+
Docs are automatically regenerated when agent versions are updated:
150+
- The `update-versions.yml` workflow runs `generate_mintlify_agents.py` after applying updates
151+
- Changes to `docs/index.mdx` are committed along with version updates
152+
153+
### Adding New Pages
154+
155+
1. Create new `.mdx` file in `docs/`
156+
2. Add the page name (without extension) to `docs.json` navigation

docs/_index.mdx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
title: Official ACP Registry
3+
description: Discover Agent Client Protocol agents
4+
---
5+
6+
<style>{`
7+
.agents-cards img,
8+
.agents-cards svg {
9+
width: 20px;
10+
height: 20px;
11+
color: currentColor;
12+
}
13+
.agents-cards {
14+
color: #111827;
15+
}
16+
.dark .agents-cards {
17+
color: #f9fafb;
18+
}
19+
`}</style>
20+
21+
<div className="agents-cards">
22+
$$AGENTS_CARDS$$
23+
</div>

docs/docs.json

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"$schema": "https://mintlify.com/docs.json",
3+
"theme": "maple",
4+
"name": "Agent Client Protocol Registry",
5+
"description": "Official registry of authenticated ACP agents",
6+
"colors": {
7+
"primary": "#0084d1",
8+
"light": "#00bcff",
9+
"dark": "#0084d1"
10+
},
11+
"background": {
12+
"color": {
13+
"light": "#f8f8f6",
14+
"dark": "#12141A"
15+
}
16+
},
17+
"fonts": {
18+
"heading": {
19+
"family": "Lora",
20+
"format": "woff2"
21+
},
22+
"body": {
23+
"family": "Public Sans",
24+
"format": "woff2"
25+
}
26+
},
27+
"favicon": {
28+
"light": "/logo/fav-light.png",
29+
"dark": "/logo/fav-dark.png"
30+
},
31+
"logo": {
32+
"light": "/logo/light.svg",
33+
"dark": "/logo/dark.svg"
34+
},
35+
"navbar": {
36+
"links": [
37+
{
38+
"label": "GitHub",
39+
"href": "https://github.com/agentclientprotocol/registry"
40+
},
41+
{
42+
"label": "agentclientprotocol.com",
43+
"href": "https://agentclientprotocol.com"
44+
},
45+
{
46+
"label": "JetBrains",
47+
"href": "https://jetbrains.com"
48+
},
49+
{
50+
"label": "Zed Industries",
51+
"href": "https://zed.dev"
52+
}
53+
]
54+
},
55+
"navigation": {
56+
"pages": [
57+
"index",
58+
"registry"
59+
]
60+
},
61+
"seo": {
62+
"metatags": {
63+
"og:image": "https://zed.dev/img/acp/og-dark.webp"
64+
},
65+
"indexing": "navigable"
66+
},
67+
"footer": {
68+
"socials": {
69+
"github": "https://github.com/agentclientprotocol/agent-client-protocol"
70+
}
71+
},
72+
"contextual": {
73+
"options": [
74+
"copy",
75+
"view"
76+
]
77+
}
78+
}

0 commit comments

Comments
 (0)