agentic-ard-kit 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ameobius
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,247 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentic-ard-kit
3
+ Version: 0.10.0
4
+ Summary: Self-hosted Agentic Resource Discovery over local scripts, agent skills and MCP servers.
5
+ Author: ameobius
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://gitlab.com/ameobius-ai/ard-kit
8
+ Project-URL: Source, https://gitlab.com/ameobius-ai/ard-kit
9
+ Project-URL: Issues, https://gitlab.com/ameobius-ai/ard-kit/-/issues
10
+ Keywords: ard,agentic-resource-discovery,mcp,agent-skills,registry,discovery
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # ard-kit
22
+
23
+ Self-hosted [Agentic Resource Discovery (ARD)](https://agenticresourcediscovery.org/)
24
+ for local and private resources: catalog your own scripts/tools into an
25
+ `ai-catalog.json`, then serve it through the two surfaces the spec defines —
26
+ a static manifest at `/.well-known/ard.json` and a dynamic
27
+ `POST /search` endpoint. `python3 selfcheck.py` asserts the pipeline
28
+ end-to-end, and `.gitlab-ci.yml` runs it plus the official conformance CLI
29
+ (`ards-project/ard-spec`) on every push where runner quota allows.
30
+
31
+ ARD is the discovery layer that sits in front of MCP (tools), Skills
32
+ (instructions), and A2A (agents). It answers one question: *"what capability
33
+ can help with this task?"* — invocation stays with the resource's own
34
+ mechanism.
35
+
36
+ ## Why this exists
37
+
38
+ The pieces started life as a private in-house integration — a catalogizer
39
+ over a large pile of local scripts and a registry serving them for
40
+ intent-based lookup. When the ARD specification was announced
41
+ (HF blog: [Agentic Resource Discovery: Let agents search](https://huggingface.co/blog/agentic-resource-discovery-launch)),
42
+ the salvageable pieces were pulled out, generalized, and aligned to the
43
+ spec. The original registry server code was lost in a workspace cleanup;
44
+ `registry.py` here is a faithful rebuild against the public shape.
45
+
46
+ ## Pieces
47
+
48
+ | File | Role |
49
+ |------|------|
50
+ | `catalogize.py` | Scans directories for `.py`/`.sh` scripts (AST docstrings, argparse flags, shell header comments), `SKILL.md` agent skills (YAML frontmatter → `text/markdown; profile="urn:air:agent-skills"` entries) and `.mcp.json` MCP client configs (→ `application/mcp-server-card+json` per server; env values never cataloged), emits ARD entries into `ai-catalog.json` plus an `ai-catalog.inspect.json` invoke-schema sidecar. Stdlib only. |
51
+ | `registry.py` | Minimal HTTP registry: serves the manifest and `POST /search` (token-overlap ranking), `POST /explore` (501 opt-out), optional `--upstreams` federation fan-out, `GET /inspect` over the sidecar, optional `--token` bearer auth. Stdlib only. |
52
+ | `mcp_server.py` | MCP stdio front over the same catalog: `ard_search` (ranked summaries) and `ard_inspect` (invoke command + CLI arguments) as MCP tools, so an editor mounts a command instead of being handed a URL. Stdlib only. |
53
+ | `selfcheck.py` | End-to-end pipeline check: catalogize a temp dir, run search, assert ranking. |
54
+ | `systemd/ard-registry.service` | Unit template for running the registry as a user service. |
55
+
56
+ No dependencies beyond Python 3.10+ stdlib.
57
+
58
+ ## Install
59
+
60
+ ```bash
61
+ pipx install agentic-ard-kit # isolated venv, three commands on PATH
62
+ pipx install . # same, from a checkout
63
+ ```
64
+
65
+ This installs `ard-catalogize`, `ard-registry` and `ard-mcp` — the same
66
+ entry points as `python3 catalogize.py`, `python3 registry.py` and
67
+ `python3 mcp_server.py`. Running straight from a clone stays supported and
68
+ needs no install at all.
69
+
70
+ ## Qoder plugin
71
+
72
+ ard-kit also ships as a self-contained [Qoder](https://qoder.com) plugin —
73
+ the same code plus an agent-facing wrapper:
74
+
75
+ | Component | What it gives the agent |
76
+ |-----------|-------------------------|
77
+ | `skills/ard-registry` | The discover → inspect → run → discard contract (env-driven endpoint: `ARD_REGISTRY_URL`, optional `ARD_REGISTRY_TOKEN`). |
78
+ | `/ard-catalogize` | Slash command: index a script directory into `ai-catalog.json` and re-verify live. |
79
+ | `/ard-serve` | Slash command: serve a catalog, confirm via `/health`. |
80
+ | `bin/ard-registry`, `bin/ard-catalogize` | Entry points added to PATH (stdlib-only, no install step). |
81
+
82
+ ```bash
83
+ qoder plugins install ./ard-kit # then /plugins reload
84
+ qoder plugins validate ./ard-kit # manifest + component check
85
+ ```
86
+
87
+ ## Quickstart
88
+
89
+ ```bash
90
+ # 1. Catalog your scripts and agent skills (default scan dir: ./scripts)
91
+ python3 catalogize.py --dir scripts --dir .agents/skills --host myhost.example.com
92
+
93
+ # 2. Serve it
94
+ python3 registry.py --catalog ai-catalog.json --port 8390
95
+
96
+ # 3. Search (the ARD registry API shape)
97
+ curl -s http://127.0.0.1:8390/search \
98
+ -H 'Content-Type: application/json' \
99
+ -d '{"query": {"text": "scan subdomains"}, "pageSize": 5}'
100
+
101
+ # 4. Inspect before running (invoke command + CLI arguments)
102
+ curl -s 'http://127.0.0.1:8390/inspect?identifier=urn:air:myhost.example.com:script:scripts:scan_subdomains'
103
+
104
+ # 5. Static manifest (for crawlers / federation)
105
+ curl -s http://127.0.0.1:8390/.well-known/ard.json
106
+ ```
107
+
108
+ The discover → inspect → run flow mirrors commercial directories like
109
+ monid.ai, minus the marketplace: `POST /search` finds the capability,
110
+ `GET /inspect?identifier=<urn>` returns its invoke command and parsed
111
+ argparse flags (404 for unknown identifiers, 501 when the sidecar is
112
+ absent), and the run itself stays with your shell.
113
+
114
+ **For clients:** the registry is stateless and nothing attaches to your
115
+ session. `POST /search` returns ranked summaries only; pull a full invoke
116
+ schema via `/inspect` for the single entry you actually run. Discard both
117
+ afterwards — keep the URN if you might reuse the tool, not the payload.
118
+ Discovery costs a query, not a mounting: there is nothing to unload because
119
+ nothing was loaded.
120
+
121
+ Require a bearer token on every endpoint except `/health` when the registry
122
+ leaves loopback. For service deployments prefer the `ARD_REGISTRY_TOKEN`
123
+ environment variable over `--token` — the command line is world-readable:
124
+
125
+ ```bash
126
+ python3 registry.py --catalog ai-catalog.json --port 8390 --token "$(openssl rand -hex 16)"
127
+ # or: ARD_REGISTRY_TOKEN=<token> python3 registry.py --catalog ai-catalog.json --port 8390
128
+ ```
129
+
130
+ A token that is set but empty is rejected at startup (fail closed).
131
+
132
+ Federate with peer registries — with `"federation": "auto"` (default) queries
133
+ fan out to `--upstreams` and results merge (every result names its `source`
134
+ registry and carries a clamped score); `"federation": "referrals"` returns the peers in
135
+ a `referrals` array instead; `"federation": "none"` stays local:
136
+
137
+ ```bash
138
+ python3 registry.py --catalog ai-catalog.json --port 8390 \
139
+ --upstreams https://peer.example.com --public-url https://me.example.com
140
+ ```
141
+
142
+ Self-check the whole pipeline:
143
+
144
+ ```bash
145
+ python3 selfcheck.py
146
+ ```
147
+
148
+ ## MCP front
149
+
150
+ The registry is HTTP, which means something has to hand the agent a URL
151
+ first. Editors that speak MCP mount a command instead, so the same catalog
152
+ is also served over stdio — no server to start, no port, no token:
153
+
154
+ ```json
155
+ {
156
+ "mcpServers": {
157
+ "ard": {
158
+ "command": "python3",
159
+ "args": ["/path/to/ard-kit/mcp_server.py",
160
+ "--catalog", "/path/to/ai-catalog.json"]
161
+ }
162
+ }
163
+ }
164
+ ```
165
+
166
+ Installed through pipx, the same front is `"command": "ard-mcp"` with no
167
+ path to keep in sync.
168
+
169
+ Two tools, the same discover → inspect → run contract:
170
+
171
+ | Tool | Returns |
172
+ |------|---------|
173
+ | `ard_search` | Ranked summaries (`identifier`, `displayName`, `description`, `type`, `score`) for an intent, optionally filtered by media type. |
174
+ | `ard_inspect` | The invoke command and parsed CLI arguments for one `urn:air:` identifier. |
175
+
176
+ Search deliberately returns summaries only: the invoke schema arrives once,
177
+ for the single entry the agent actually runs. The catalog is re-read per
178
+ call, so re-running `catalogize.py` is picked up without a restart, and the
179
+ host owns the process lifetime — the server exits when stdin closes.
180
+
181
+ ## Entry shape
182
+
183
+ Each catalog entry carries the fields ARD consumers key on:
184
+
185
+ ```json
186
+ {
187
+ "@context": "https://agenticresourcediscovery.org/context/v1",
188
+ "identifier": "urn:air:myhost.example.com:script:scripts:scan_subdomains",
189
+ "displayName": "scan_subdomains",
190
+ "description": "Enumerate subdomains via passive sources",
191
+ "type": "application/vnd.ard-kit.script+json",
192
+ "url": "file:///path/to/scripts/scan_subdomains.py",
193
+ "tags": ["scan", "subdomains", "recon"],
194
+ "aliases": ["scan_subdomains"],
195
+ "representativeQueries": [
196
+ "Enumerate subdomains via passive sources",
197
+ "scan", "subdomains", "recon"
198
+ ],
199
+ "metadata": { "invoke": "python3 scripts/scan_subdomains.py", ... }
200
+ }
201
+ ```
202
+
203
+ `representativeQueries` lead with the natural description phrase and pad
204
+ with keywords, so both sentence-style and token-style agent queries hit.
205
+ Every entry carries the field: when a resource offers no keywords, the file
206
+ or skill name is split to pad the list, which is always 2–5 phrases.
207
+ Entries keep exactly one of `url`/`data` (spec §3.4) and scalar-only
208
+ `metadata` values, and the manifest envelope carries only
209
+ `specVersion`/`host`/`entries` — the shape the official
210
+ `ai-catalog.schema.json` validates.
211
+
212
+ The `type` media type is free-form per the spec, but entries use a standard
213
+ name wherever one exists — `application/mcp-server-card+json` for MCP servers,
214
+ `text/markdown; profile="urn:air:agent-skills"` for agent skills — so any
215
+ conformant registry routes them without a local mapping. Plain local scripts
216
+ have no standard type yet and keep the vendor one.
217
+ Identifiers follow the spec's Appendix C form
218
+ (`urn:air:<publisher>:<namespace>:<name>`), and the served manifest prepends
219
+ a self-advert entry of type `application/ai-registry+json` so peers can
220
+ discover this registry's search base URL. Search results carry a `score` in
221
+ the spec's 0–100 relevance band (relevance only — ARD decouples trust into
222
+ the trust manifest, §5).
223
+
224
+ ## Prior art / positioning
225
+
226
+ - [HF Discover](https://github.com/huggingface/hf-discover) — reference
227
+ implementation over the Hugging Face Hub; federated, semantic search.
228
+ - [ARD spec](https://github.com/ards-project/ard-spec) — the standard itself
229
+ (Apache-2.0).
230
+ - [monid.ai](https://monid.ai/docs/guide/quickstart-skill) — commercial take
231
+ on the same pattern: a CLI/Skill teaching an agent to `discover → inspect →
232
+ run` endpoints by intent. The difference: monid is a paid marketplace of
233
+ third-party data endpoints behind an API key; ard-kit is the self-hosted,
234
+ no-network, no-account version for resources you already own.
235
+
236
+ Known limitation: search here is lexical token overlap, not semantic ranking.
237
+ That is deliberate — zero dependencies, and good enough for a few thousand
238
+ private entries. The upgrade path is embeddings behind the same endpoint.
239
+
240
+ ## License
241
+
242
+ MIT.
243
+
244
+ ## Acknowledgements
245
+
246
+ Developed and hardened in [Qoder](https://qoder.com) — from the ARD v0.91
247
+ conformance rebuild through the ultra-review cycle.
@@ -0,0 +1,227 @@
1
+ # ard-kit
2
+
3
+ Self-hosted [Agentic Resource Discovery (ARD)](https://agenticresourcediscovery.org/)
4
+ for local and private resources: catalog your own scripts/tools into an
5
+ `ai-catalog.json`, then serve it through the two surfaces the spec defines —
6
+ a static manifest at `/.well-known/ard.json` and a dynamic
7
+ `POST /search` endpoint. `python3 selfcheck.py` asserts the pipeline
8
+ end-to-end, and `.gitlab-ci.yml` runs it plus the official conformance CLI
9
+ (`ards-project/ard-spec`) on every push where runner quota allows.
10
+
11
+ ARD is the discovery layer that sits in front of MCP (tools), Skills
12
+ (instructions), and A2A (agents). It answers one question: *"what capability
13
+ can help with this task?"* — invocation stays with the resource's own
14
+ mechanism.
15
+
16
+ ## Why this exists
17
+
18
+ The pieces started life as a private in-house integration — a catalogizer
19
+ over a large pile of local scripts and a registry serving them for
20
+ intent-based lookup. When the ARD specification was announced
21
+ (HF blog: [Agentic Resource Discovery: Let agents search](https://huggingface.co/blog/agentic-resource-discovery-launch)),
22
+ the salvageable pieces were pulled out, generalized, and aligned to the
23
+ spec. The original registry server code was lost in a workspace cleanup;
24
+ `registry.py` here is a faithful rebuild against the public shape.
25
+
26
+ ## Pieces
27
+
28
+ | File | Role |
29
+ |------|------|
30
+ | `catalogize.py` | Scans directories for `.py`/`.sh` scripts (AST docstrings, argparse flags, shell header comments), `SKILL.md` agent skills (YAML frontmatter → `text/markdown; profile="urn:air:agent-skills"` entries) and `.mcp.json` MCP client configs (→ `application/mcp-server-card+json` per server; env values never cataloged), emits ARD entries into `ai-catalog.json` plus an `ai-catalog.inspect.json` invoke-schema sidecar. Stdlib only. |
31
+ | `registry.py` | Minimal HTTP registry: serves the manifest and `POST /search` (token-overlap ranking), `POST /explore` (501 opt-out), optional `--upstreams` federation fan-out, `GET /inspect` over the sidecar, optional `--token` bearer auth. Stdlib only. |
32
+ | `mcp_server.py` | MCP stdio front over the same catalog: `ard_search` (ranked summaries) and `ard_inspect` (invoke command + CLI arguments) as MCP tools, so an editor mounts a command instead of being handed a URL. Stdlib only. |
33
+ | `selfcheck.py` | End-to-end pipeline check: catalogize a temp dir, run search, assert ranking. |
34
+ | `systemd/ard-registry.service` | Unit template for running the registry as a user service. |
35
+
36
+ No dependencies beyond Python 3.10+ stdlib.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pipx install agentic-ard-kit # isolated venv, three commands on PATH
42
+ pipx install . # same, from a checkout
43
+ ```
44
+
45
+ This installs `ard-catalogize`, `ard-registry` and `ard-mcp` — the same
46
+ entry points as `python3 catalogize.py`, `python3 registry.py` and
47
+ `python3 mcp_server.py`. Running straight from a clone stays supported and
48
+ needs no install at all.
49
+
50
+ ## Qoder plugin
51
+
52
+ ard-kit also ships as a self-contained [Qoder](https://qoder.com) plugin —
53
+ the same code plus an agent-facing wrapper:
54
+
55
+ | Component | What it gives the agent |
56
+ |-----------|-------------------------|
57
+ | `skills/ard-registry` | The discover → inspect → run → discard contract (env-driven endpoint: `ARD_REGISTRY_URL`, optional `ARD_REGISTRY_TOKEN`). |
58
+ | `/ard-catalogize` | Slash command: index a script directory into `ai-catalog.json` and re-verify live. |
59
+ | `/ard-serve` | Slash command: serve a catalog, confirm via `/health`. |
60
+ | `bin/ard-registry`, `bin/ard-catalogize` | Entry points added to PATH (stdlib-only, no install step). |
61
+
62
+ ```bash
63
+ qoder plugins install ./ard-kit # then /plugins reload
64
+ qoder plugins validate ./ard-kit # manifest + component check
65
+ ```
66
+
67
+ ## Quickstart
68
+
69
+ ```bash
70
+ # 1. Catalog your scripts and agent skills (default scan dir: ./scripts)
71
+ python3 catalogize.py --dir scripts --dir .agents/skills --host myhost.example.com
72
+
73
+ # 2. Serve it
74
+ python3 registry.py --catalog ai-catalog.json --port 8390
75
+
76
+ # 3. Search (the ARD registry API shape)
77
+ curl -s http://127.0.0.1:8390/search \
78
+ -H 'Content-Type: application/json' \
79
+ -d '{"query": {"text": "scan subdomains"}, "pageSize": 5}'
80
+
81
+ # 4. Inspect before running (invoke command + CLI arguments)
82
+ curl -s 'http://127.0.0.1:8390/inspect?identifier=urn:air:myhost.example.com:script:scripts:scan_subdomains'
83
+
84
+ # 5. Static manifest (for crawlers / federation)
85
+ curl -s http://127.0.0.1:8390/.well-known/ard.json
86
+ ```
87
+
88
+ The discover → inspect → run flow mirrors commercial directories like
89
+ monid.ai, minus the marketplace: `POST /search` finds the capability,
90
+ `GET /inspect?identifier=<urn>` returns its invoke command and parsed
91
+ argparse flags (404 for unknown identifiers, 501 when the sidecar is
92
+ absent), and the run itself stays with your shell.
93
+
94
+ **For clients:** the registry is stateless and nothing attaches to your
95
+ session. `POST /search` returns ranked summaries only; pull a full invoke
96
+ schema via `/inspect` for the single entry you actually run. Discard both
97
+ afterwards — keep the URN if you might reuse the tool, not the payload.
98
+ Discovery costs a query, not a mounting: there is nothing to unload because
99
+ nothing was loaded.
100
+
101
+ Require a bearer token on every endpoint except `/health` when the registry
102
+ leaves loopback. For service deployments prefer the `ARD_REGISTRY_TOKEN`
103
+ environment variable over `--token` — the command line is world-readable:
104
+
105
+ ```bash
106
+ python3 registry.py --catalog ai-catalog.json --port 8390 --token "$(openssl rand -hex 16)"
107
+ # or: ARD_REGISTRY_TOKEN=<token> python3 registry.py --catalog ai-catalog.json --port 8390
108
+ ```
109
+
110
+ A token that is set but empty is rejected at startup (fail closed).
111
+
112
+ Federate with peer registries — with `"federation": "auto"` (default) queries
113
+ fan out to `--upstreams` and results merge (every result names its `source`
114
+ registry and carries a clamped score); `"federation": "referrals"` returns the peers in
115
+ a `referrals` array instead; `"federation": "none"` stays local:
116
+
117
+ ```bash
118
+ python3 registry.py --catalog ai-catalog.json --port 8390 \
119
+ --upstreams https://peer.example.com --public-url https://me.example.com
120
+ ```
121
+
122
+ Self-check the whole pipeline:
123
+
124
+ ```bash
125
+ python3 selfcheck.py
126
+ ```
127
+
128
+ ## MCP front
129
+
130
+ The registry is HTTP, which means something has to hand the agent a URL
131
+ first. Editors that speak MCP mount a command instead, so the same catalog
132
+ is also served over stdio — no server to start, no port, no token:
133
+
134
+ ```json
135
+ {
136
+ "mcpServers": {
137
+ "ard": {
138
+ "command": "python3",
139
+ "args": ["/path/to/ard-kit/mcp_server.py",
140
+ "--catalog", "/path/to/ai-catalog.json"]
141
+ }
142
+ }
143
+ }
144
+ ```
145
+
146
+ Installed through pipx, the same front is `"command": "ard-mcp"` with no
147
+ path to keep in sync.
148
+
149
+ Two tools, the same discover → inspect → run contract:
150
+
151
+ | Tool | Returns |
152
+ |------|---------|
153
+ | `ard_search` | Ranked summaries (`identifier`, `displayName`, `description`, `type`, `score`) for an intent, optionally filtered by media type. |
154
+ | `ard_inspect` | The invoke command and parsed CLI arguments for one `urn:air:` identifier. |
155
+
156
+ Search deliberately returns summaries only: the invoke schema arrives once,
157
+ for the single entry the agent actually runs. The catalog is re-read per
158
+ call, so re-running `catalogize.py` is picked up without a restart, and the
159
+ host owns the process lifetime — the server exits when stdin closes.
160
+
161
+ ## Entry shape
162
+
163
+ Each catalog entry carries the fields ARD consumers key on:
164
+
165
+ ```json
166
+ {
167
+ "@context": "https://agenticresourcediscovery.org/context/v1",
168
+ "identifier": "urn:air:myhost.example.com:script:scripts:scan_subdomains",
169
+ "displayName": "scan_subdomains",
170
+ "description": "Enumerate subdomains via passive sources",
171
+ "type": "application/vnd.ard-kit.script+json",
172
+ "url": "file:///path/to/scripts/scan_subdomains.py",
173
+ "tags": ["scan", "subdomains", "recon"],
174
+ "aliases": ["scan_subdomains"],
175
+ "representativeQueries": [
176
+ "Enumerate subdomains via passive sources",
177
+ "scan", "subdomains", "recon"
178
+ ],
179
+ "metadata": { "invoke": "python3 scripts/scan_subdomains.py", ... }
180
+ }
181
+ ```
182
+
183
+ `representativeQueries` lead with the natural description phrase and pad
184
+ with keywords, so both sentence-style and token-style agent queries hit.
185
+ Every entry carries the field: when a resource offers no keywords, the file
186
+ or skill name is split to pad the list, which is always 2–5 phrases.
187
+ Entries keep exactly one of `url`/`data` (spec §3.4) and scalar-only
188
+ `metadata` values, and the manifest envelope carries only
189
+ `specVersion`/`host`/`entries` — the shape the official
190
+ `ai-catalog.schema.json` validates.
191
+
192
+ The `type` media type is free-form per the spec, but entries use a standard
193
+ name wherever one exists — `application/mcp-server-card+json` for MCP servers,
194
+ `text/markdown; profile="urn:air:agent-skills"` for agent skills — so any
195
+ conformant registry routes them without a local mapping. Plain local scripts
196
+ have no standard type yet and keep the vendor one.
197
+ Identifiers follow the spec's Appendix C form
198
+ (`urn:air:<publisher>:<namespace>:<name>`), and the served manifest prepends
199
+ a self-advert entry of type `application/ai-registry+json` so peers can
200
+ discover this registry's search base URL. Search results carry a `score` in
201
+ the spec's 0–100 relevance band (relevance only — ARD decouples trust into
202
+ the trust manifest, §5).
203
+
204
+ ## Prior art / positioning
205
+
206
+ - [HF Discover](https://github.com/huggingface/hf-discover) — reference
207
+ implementation over the Hugging Face Hub; federated, semantic search.
208
+ - [ARD spec](https://github.com/ards-project/ard-spec) — the standard itself
209
+ (Apache-2.0).
210
+ - [monid.ai](https://monid.ai/docs/guide/quickstart-skill) — commercial take
211
+ on the same pattern: a CLI/Skill teaching an agent to `discover → inspect →
212
+ run` endpoints by intent. The difference: monid is a paid marketplace of
213
+ third-party data endpoints behind an API key; ard-kit is the self-hosted,
214
+ no-network, no-account version for resources you already own.
215
+
216
+ Known limitation: search here is lexical token overlap, not semantic ranking.
217
+ That is deliberate — zero dependencies, and good enough for a few thousand
218
+ private entries. The upgrade path is embeddings behind the same endpoint.
219
+
220
+ ## License
221
+
222
+ MIT.
223
+
224
+ ## Acknowledgements
225
+
226
+ Developed and hardened in [Qoder](https://qoder.com) — from the ARD v0.91
227
+ conformance rebuild through the ultra-review cycle.