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.
- agentic_ard_kit-0.10.0/LICENSE +21 -0
- agentic_ard_kit-0.10.0/PKG-INFO +247 -0
- agentic_ard_kit-0.10.0/README.md +227 -0
- agentic_ard_kit-0.10.0/agentic_ard_kit.egg-info/PKG-INFO +247 -0
- agentic_ard_kit-0.10.0/agentic_ard_kit.egg-info/SOURCES.txt +11 -0
- agentic_ard_kit-0.10.0/agentic_ard_kit.egg-info/dependency_links.txt +1 -0
- agentic_ard_kit-0.10.0/agentic_ard_kit.egg-info/entry_points.txt +4 -0
- agentic_ard_kit-0.10.0/agentic_ard_kit.egg-info/top_level.txt +3 -0
- agentic_ard_kit-0.10.0/catalogize.py +651 -0
- agentic_ard_kit-0.10.0/mcp_server.py +254 -0
- agentic_ard_kit-0.10.0/pyproject.toml +46 -0
- agentic_ard_kit-0.10.0/registry.py +426 -0
- agentic_ard_kit-0.10.0/setup.cfg +4 -0
|
@@ -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.
|