agent-interface-standard 0.1.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.
- agent_interface_standard-0.1.0/.gitignore +6 -0
- agent_interface_standard-0.1.0/PKG-INFO +79 -0
- agent_interface_standard-0.1.0/README.md +64 -0
- agent_interface_standard-0.1.0/pyproject.toml +24 -0
- agent_interface_standard-0.1.0/src/__init__.py +0 -0
- agent_interface_standard-0.1.0/src/schema.py +173 -0
- agent_interface_standard-0.1.0/src/server.py +24 -0
- agent_interface_standard-0.1.0/src/tools/__init__.py +0 -0
- agent_interface_standard-0.1.0/src/tools/standard_tools.py +217 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-interface-standard
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Schema.org for AI agents — the open standard for how businesses describe their services to AI agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/AiAgentKarl/agent-interface-standard
|
|
6
|
+
Project-URL: Repository, https://github.com/AiAgentKarl/agent-interface-standard
|
|
7
|
+
Author: AiAgentKarl
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: agent-interface,ai-agents,business,mcp,protocol,schema,standard
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: httpx>=0.27.0
|
|
12
|
+
Requires-Dist: mcp>=1.0.0
|
|
13
|
+
Requires-Dist: pydantic>=2.0.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# Agent Interface Standard 🌐
|
|
17
|
+
|
|
18
|
+
**Schema.org for AI Agents** — the open standard for how businesses describe their services to AI agents.
|
|
19
|
+
|
|
20
|
+
## The Vision
|
|
21
|
+
|
|
22
|
+
Schema.org made websites machine-readable for search engines. **Agent Interface Standard** makes businesses machine-readable for AI agents.
|
|
23
|
+
|
|
24
|
+
Businesses publish a simple JSON spec at `/.well-known/agent-interface.json` describing what services they offer and how agents can interact with them.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install agent-interface-standard
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{"mcpServers": {"agent-interface": {"command": "uvx", "args": ["agent-interface-standard"]}}}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Tools
|
|
37
|
+
|
|
38
|
+
| Tool | Description |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| `get_spec_template` | Get a blank template to fill out |
|
|
41
|
+
| `get_example_spec` | See a complete example (restaurant) |
|
|
42
|
+
| `validate_interface_spec` | Check your spec for errors |
|
|
43
|
+
| `register_business` | Register a business in the directory |
|
|
44
|
+
| `search_businesses` | Find agent-accessible businesses |
|
|
45
|
+
| `get_business_capabilities` | See what a business offers |
|
|
46
|
+
| `fetch_remote_spec` | Fetch a spec from a URL |
|
|
47
|
+
|
|
48
|
+
## The Spec Format
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"agent_interface": "0.1.0",
|
|
53
|
+
"business": {
|
|
54
|
+
"name": "My Business",
|
|
55
|
+
"description": "What we do",
|
|
56
|
+
"category": "e_commerce"
|
|
57
|
+
},
|
|
58
|
+
"capabilities": [
|
|
59
|
+
{
|
|
60
|
+
"name": "search_products",
|
|
61
|
+
"description": "Search our product catalog",
|
|
62
|
+
"type": "search",
|
|
63
|
+
"endpoint": "https://api.mybusiness.com/search",
|
|
64
|
+
"method": "GET",
|
|
65
|
+
"parameters": [...]
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"auth": {"type": "api_key"},
|
|
69
|
+
"pricing": {"model": "freemium"}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Why This Matters
|
|
74
|
+
|
|
75
|
+
When AI agents become primary customers (not just humans), businesses need a standard way to be "agent-accessible." This is that standard.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Agent Interface Standard 🌐
|
|
2
|
+
|
|
3
|
+
**Schema.org for AI Agents** — the open standard for how businesses describe their services to AI agents.
|
|
4
|
+
|
|
5
|
+
## The Vision
|
|
6
|
+
|
|
7
|
+
Schema.org made websites machine-readable for search engines. **Agent Interface Standard** makes businesses machine-readable for AI agents.
|
|
8
|
+
|
|
9
|
+
Businesses publish a simple JSON spec at `/.well-known/agent-interface.json` describing what services they offer and how agents can interact with them.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install agent-interface-standard
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{"mcpServers": {"agent-interface": {"command": "uvx", "args": ["agent-interface-standard"]}}}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Tools
|
|
22
|
+
|
|
23
|
+
| Tool | Description |
|
|
24
|
+
|------|-------------|
|
|
25
|
+
| `get_spec_template` | Get a blank template to fill out |
|
|
26
|
+
| `get_example_spec` | See a complete example (restaurant) |
|
|
27
|
+
| `validate_interface_spec` | Check your spec for errors |
|
|
28
|
+
| `register_business` | Register a business in the directory |
|
|
29
|
+
| `search_businesses` | Find agent-accessible businesses |
|
|
30
|
+
| `get_business_capabilities` | See what a business offers |
|
|
31
|
+
| `fetch_remote_spec` | Fetch a spec from a URL |
|
|
32
|
+
|
|
33
|
+
## The Spec Format
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"agent_interface": "0.1.0",
|
|
38
|
+
"business": {
|
|
39
|
+
"name": "My Business",
|
|
40
|
+
"description": "What we do",
|
|
41
|
+
"category": "e_commerce"
|
|
42
|
+
},
|
|
43
|
+
"capabilities": [
|
|
44
|
+
{
|
|
45
|
+
"name": "search_products",
|
|
46
|
+
"description": "Search our product catalog",
|
|
47
|
+
"type": "search",
|
|
48
|
+
"endpoint": "https://api.mybusiness.com/search",
|
|
49
|
+
"method": "GET",
|
|
50
|
+
"parameters": [...]
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"auth": {"type": "api_key"},
|
|
54
|
+
"pricing": {"model": "freemium"}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Why This Matters
|
|
59
|
+
|
|
60
|
+
When AI agents become primary customers (not just humans), businesses need a standard way to be "agent-accessible." This is that standard.
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agent-interface-standard"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Schema.org for AI agents — the open standard for how businesses describe their services to AI agents"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{name = "AiAgentKarl"}]
|
|
13
|
+
keywords = ["mcp", "agent-interface", "schema", "standard", "business", "ai-agents", "protocol"]
|
|
14
|
+
dependencies = ["mcp>=1.0.0", "httpx>=0.27.0", "pydantic>=2.0.0"]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://github.com/AiAgentKarl/agent-interface-standard"
|
|
18
|
+
Repository = "https://github.com/AiAgentKarl/agent-interface-standard"
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
agent-interface = "src.server:main"
|
|
22
|
+
|
|
23
|
+
[tool.hatch.build.targets.wheel]
|
|
24
|
+
packages = ["src"]
|
|
File without changes
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""Agent Interface Schema — der offene Standard für agent-lesbare Business-Beschreibungen.
|
|
2
|
+
|
|
3
|
+
Definiert das JSON-Format das Unternehmen veröffentlichen können,
|
|
4
|
+
damit AI-Agents ihre Services automatisch verstehen und nutzen können.
|
|
5
|
+
Vergleichbar mit Schema.org für Suchmaschinen, aber für AI-Agents.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import sqlite3
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
|
|
13
|
+
DB_PATH = Path.home() / ".agent-interface" / "registry.db"
|
|
14
|
+
|
|
15
|
+
# Die Standard-Spec Version
|
|
16
|
+
SPEC_VERSION = "0.1.0"
|
|
17
|
+
|
|
18
|
+
# Beispiel einer Agent Interface Spec
|
|
19
|
+
EXAMPLE_SPEC = {
|
|
20
|
+
"agent_interface": SPEC_VERSION,
|
|
21
|
+
"business": {
|
|
22
|
+
"name": "Example Restaurant",
|
|
23
|
+
"description": "Italian restaurant with delivery",
|
|
24
|
+
"category": "food_delivery",
|
|
25
|
+
"website": "https://example-restaurant.com",
|
|
26
|
+
"location": {"city": "Berlin", "country": "DE"},
|
|
27
|
+
},
|
|
28
|
+
"capabilities": [
|
|
29
|
+
{
|
|
30
|
+
"name": "view_menu",
|
|
31
|
+
"description": "Browse the restaurant menu",
|
|
32
|
+
"type": "read",
|
|
33
|
+
"endpoint": "https://api.example-restaurant.com/menu",
|
|
34
|
+
"method": "GET",
|
|
35
|
+
"parameters": [
|
|
36
|
+
{"name": "category", "type": "string", "required": False,
|
|
37
|
+
"description": "Filter by category (pizza, pasta, salad)"}
|
|
38
|
+
],
|
|
39
|
+
"returns": "List of menu items with prices",
|
|
40
|
+
"auth_required": False,
|
|
41
|
+
"rate_limit": "60/min",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "place_order",
|
|
45
|
+
"description": "Place a delivery order",
|
|
46
|
+
"type": "transaction",
|
|
47
|
+
"endpoint": "https://api.example-restaurant.com/orders",
|
|
48
|
+
"method": "POST",
|
|
49
|
+
"parameters": [
|
|
50
|
+
{"name": "items", "type": "array", "required": True,
|
|
51
|
+
"description": "List of item IDs and quantities"},
|
|
52
|
+
{"name": "delivery_address", "type": "string", "required": True,
|
|
53
|
+
"description": "Full delivery address"},
|
|
54
|
+
{"name": "payment_method", "type": "string", "required": True,
|
|
55
|
+
"description": "Payment method (card, cash, x402)"},
|
|
56
|
+
],
|
|
57
|
+
"returns": "Order confirmation with estimated delivery time",
|
|
58
|
+
"auth_required": True,
|
|
59
|
+
"cost": {"currency": "EUR", "estimate": "10-30"},
|
|
60
|
+
"confirmation_required": True,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "track_order",
|
|
64
|
+
"description": "Track an existing order status",
|
|
65
|
+
"type": "read",
|
|
66
|
+
"endpoint": "https://api.example-restaurant.com/orders/{order_id}",
|
|
67
|
+
"method": "GET",
|
|
68
|
+
"parameters": [
|
|
69
|
+
{"name": "order_id", "type": "string", "required": True,
|
|
70
|
+
"description": "The order ID from place_order"}
|
|
71
|
+
],
|
|
72
|
+
"returns": "Order status and estimated delivery time",
|
|
73
|
+
"auth_required": True,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
"auth": {
|
|
77
|
+
"type": "api_key",
|
|
78
|
+
"header": "X-API-Key",
|
|
79
|
+
"registration_url": "https://example-restaurant.com/developers",
|
|
80
|
+
},
|
|
81
|
+
"pricing": {
|
|
82
|
+
"model": "per_transaction",
|
|
83
|
+
"details": "Menu browsing is free. Orders are charged at menu prices.",
|
|
84
|
+
},
|
|
85
|
+
"contact": {
|
|
86
|
+
"support_email": "api@example-restaurant.com",
|
|
87
|
+
"docs_url": "https://docs.example-restaurant.com",
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Template-Spezifikation die Unternehmen ausfüllen können
|
|
92
|
+
BUSINESS_TEMPLATE = {
|
|
93
|
+
"agent_interface": SPEC_VERSION,
|
|
94
|
+
"business": {
|
|
95
|
+
"name": "",
|
|
96
|
+
"description": "",
|
|
97
|
+
"category": "",
|
|
98
|
+
"website": "",
|
|
99
|
+
"location": {"city": "", "country": ""},
|
|
100
|
+
},
|
|
101
|
+
"capabilities": [],
|
|
102
|
+
"auth": {"type": "none"},
|
|
103
|
+
"pricing": {"model": "free"},
|
|
104
|
+
"contact": {},
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Bekannte Business-Kategorien
|
|
108
|
+
CATEGORIES = [
|
|
109
|
+
"e_commerce", "food_delivery", "travel_booking", "financial_services",
|
|
110
|
+
"healthcare", "real_estate", "transportation", "education",
|
|
111
|
+
"entertainment", "professional_services", "saas", "marketplace",
|
|
112
|
+
"government", "utilities", "insurance", "logistics",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
# Capability-Typen
|
|
116
|
+
CAPABILITY_TYPES = [
|
|
117
|
+
"read", # Daten lesen (GET)
|
|
118
|
+
"write", # Daten schreiben (POST/PUT)
|
|
119
|
+
"transaction", # Kostenpflichtige Aktion
|
|
120
|
+
"search", # Suche
|
|
121
|
+
"booking", # Reservierung/Buchung
|
|
122
|
+
"subscription", # Abo-Verwaltung
|
|
123
|
+
"notification", # Benachrichtigungen
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _get_db():
|
|
128
|
+
"""Datenbank für registrierte Business-Interfaces."""
|
|
129
|
+
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
130
|
+
conn = sqlite3.connect(str(DB_PATH))
|
|
131
|
+
conn.row_factory = sqlite3.Row
|
|
132
|
+
conn.execute("""
|
|
133
|
+
CREATE TABLE IF NOT EXISTS interfaces (
|
|
134
|
+
id TEXT PRIMARY KEY,
|
|
135
|
+
business_name TEXT NOT NULL,
|
|
136
|
+
description TEXT DEFAULT '',
|
|
137
|
+
category TEXT DEFAULT '',
|
|
138
|
+
spec_json TEXT NOT NULL,
|
|
139
|
+
capabilities_count INTEGER DEFAULT 0,
|
|
140
|
+
website TEXT DEFAULT '',
|
|
141
|
+
registered_at TEXT NOT NULL
|
|
142
|
+
)
|
|
143
|
+
""")
|
|
144
|
+
conn.commit()
|
|
145
|
+
return conn
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def validate_spec(spec: dict) -> list[str]:
|
|
149
|
+
"""Agent Interface Spec validieren. Gibt Liste von Fehlern zurück."""
|
|
150
|
+
errors = []
|
|
151
|
+
|
|
152
|
+
if "agent_interface" not in spec:
|
|
153
|
+
errors.append("Missing 'agent_interface' version field")
|
|
154
|
+
|
|
155
|
+
business = spec.get("business", {})
|
|
156
|
+
if not business.get("name"):
|
|
157
|
+
errors.append("Missing 'business.name'")
|
|
158
|
+
if not business.get("description"):
|
|
159
|
+
errors.append("Missing 'business.description'")
|
|
160
|
+
|
|
161
|
+
capabilities = spec.get("capabilities", [])
|
|
162
|
+
if not capabilities:
|
|
163
|
+
errors.append("No capabilities defined — at least one required")
|
|
164
|
+
|
|
165
|
+
for i, cap in enumerate(capabilities):
|
|
166
|
+
if not cap.get("name"):
|
|
167
|
+
errors.append(f"Capability {i}: missing 'name'")
|
|
168
|
+
if not cap.get("description"):
|
|
169
|
+
errors.append(f"Capability {i}: missing 'description'")
|
|
170
|
+
if not cap.get("endpoint"):
|
|
171
|
+
errors.append(f"Capability {i}: missing 'endpoint'")
|
|
172
|
+
|
|
173
|
+
return errors
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Agent Interface Standard — Schema.org for AI Agents."""
|
|
2
|
+
|
|
3
|
+
from mcp.server.fastmcp import FastMCP
|
|
4
|
+
from src.tools.standard_tools import register_standard_tools
|
|
5
|
+
|
|
6
|
+
mcp = FastMCP(
|
|
7
|
+
"Agent Interface Standard",
|
|
8
|
+
instructions=(
|
|
9
|
+
"The open standard for how businesses describe their services to AI agents. "
|
|
10
|
+
"Like Schema.org made websites machine-readable for search engines, "
|
|
11
|
+
"Agent Interface Standard makes businesses machine-readable for AI agents. "
|
|
12
|
+
"Create, validate, register and discover agent-accessible business interfaces."
|
|
13
|
+
),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
register_standard_tools(mcp)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def main():
|
|
20
|
+
mcp.run(transport="stdio")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"""Standard-Tools — Agent Interface Specs erstellen, validieren und nutzen."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import httpx
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from mcp.server.fastmcp import FastMCP
|
|
7
|
+
|
|
8
|
+
from src.schema import (
|
|
9
|
+
SPEC_VERSION, EXAMPLE_SPEC, BUSINESS_TEMPLATE,
|
|
10
|
+
CATEGORIES, CAPABILITY_TYPES, validate_spec, _get_db,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def register_standard_tools(mcp: FastMCP):
|
|
15
|
+
|
|
16
|
+
@mcp.tool()
|
|
17
|
+
async def get_spec_template(category: str = "") -> dict:
|
|
18
|
+
"""Get a blank Agent Interface spec template for a business.
|
|
19
|
+
|
|
20
|
+
Returns a template that businesses can fill out to make
|
|
21
|
+
their services accessible to AI agents. Like Schema.org markup
|
|
22
|
+
but for AI agents.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
category: Business category for relevant examples (optional)
|
|
26
|
+
"""
|
|
27
|
+
return {
|
|
28
|
+
"spec_version": SPEC_VERSION,
|
|
29
|
+
"template": BUSINESS_TEMPLATE,
|
|
30
|
+
"available_categories": CATEGORIES,
|
|
31
|
+
"capability_types": CAPABILITY_TYPES,
|
|
32
|
+
"instructions": (
|
|
33
|
+
"Fill out the template with your business details and capabilities. "
|
|
34
|
+
"Each capability describes one action an AI agent can take. "
|
|
35
|
+
"Use validate_spec to check your spec before publishing."
|
|
36
|
+
),
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@mcp.tool()
|
|
40
|
+
async def get_example_spec() -> dict:
|
|
41
|
+
"""Get a complete example Agent Interface spec.
|
|
42
|
+
|
|
43
|
+
Shows a fully filled-out spec for a restaurant with
|
|
44
|
+
menu browsing, ordering, and order tracking capabilities.
|
|
45
|
+
Use this as a reference when creating your own spec.
|
|
46
|
+
"""
|
|
47
|
+
return {
|
|
48
|
+
"description": "Complete example spec for a restaurant business",
|
|
49
|
+
"spec": EXAMPLE_SPEC,
|
|
50
|
+
"note": "This shows all supported fields. Not all fields are required.",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@mcp.tool()
|
|
54
|
+
async def validate_interface_spec(spec_json: str) -> dict:
|
|
55
|
+
"""Validate an Agent Interface spec for correctness.
|
|
56
|
+
|
|
57
|
+
Checks that all required fields are present and properly formatted.
|
|
58
|
+
Returns a list of errors if the spec is invalid.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
spec_json: The spec as a JSON string
|
|
62
|
+
"""
|
|
63
|
+
try:
|
|
64
|
+
spec = json.loads(spec_json)
|
|
65
|
+
except json.JSONDecodeError as e:
|
|
66
|
+
return {"valid": False, "errors": [f"Invalid JSON: {e}"]}
|
|
67
|
+
|
|
68
|
+
errors = validate_spec(spec)
|
|
69
|
+
|
|
70
|
+
if errors:
|
|
71
|
+
return {"valid": False, "errors": errors, "error_count": len(errors)}
|
|
72
|
+
|
|
73
|
+
caps = spec.get("capabilities", [])
|
|
74
|
+
return {
|
|
75
|
+
"valid": True,
|
|
76
|
+
"spec_version": spec.get("agent_interface", "unknown"),
|
|
77
|
+
"business": spec.get("business", {}).get("name", ""),
|
|
78
|
+
"capabilities_count": len(caps),
|
|
79
|
+
"message": "Spec is valid and ready to publish.",
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@mcp.tool()
|
|
83
|
+
async def register_business(spec_json: str, business_id: str = "") -> dict:
|
|
84
|
+
"""Register a business interface spec in the local directory.
|
|
85
|
+
|
|
86
|
+
Makes the business discoverable by agents through search_businesses.
|
|
87
|
+
The spec is stored locally and persists between sessions.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
spec_json: The complete Agent Interface spec as JSON
|
|
91
|
+
business_id: Custom ID (auto-generated from business name if empty)
|
|
92
|
+
"""
|
|
93
|
+
try:
|
|
94
|
+
spec = json.loads(spec_json)
|
|
95
|
+
except json.JSONDecodeError as e:
|
|
96
|
+
return {"error": f"Invalid JSON: {e}"}
|
|
97
|
+
|
|
98
|
+
errors = validate_spec(spec)
|
|
99
|
+
if errors:
|
|
100
|
+
return {"error": "Invalid spec", "errors": errors}
|
|
101
|
+
|
|
102
|
+
business = spec.get("business", {})
|
|
103
|
+
name = business.get("name", "Unknown")
|
|
104
|
+
|
|
105
|
+
if not business_id:
|
|
106
|
+
business_id = name.lower().replace(" ", "-").replace(".", "-")[:50]
|
|
107
|
+
|
|
108
|
+
conn = _get_db()
|
|
109
|
+
conn.execute("""
|
|
110
|
+
INSERT OR REPLACE INTO interfaces
|
|
111
|
+
(id, business_name, description, category, spec_json,
|
|
112
|
+
capabilities_count, website, registered_at)
|
|
113
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
114
|
+
""", (
|
|
115
|
+
business_id, name, business.get("description", ""),
|
|
116
|
+
business.get("category", ""),
|
|
117
|
+
json.dumps(spec), len(spec.get("capabilities", [])),
|
|
118
|
+
business.get("website", ""), datetime.utcnow().isoformat(),
|
|
119
|
+
))
|
|
120
|
+
conn.commit()
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
"status": "registered",
|
|
124
|
+
"business_id": business_id,
|
|
125
|
+
"name": name,
|
|
126
|
+
"capabilities": len(spec.get("capabilities", [])),
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@mcp.tool()
|
|
130
|
+
async def search_businesses(query: str, category: str = "") -> dict:
|
|
131
|
+
"""Search for agent-accessible businesses.
|
|
132
|
+
|
|
133
|
+
Find businesses that have published Agent Interface specs,
|
|
134
|
+
making their services available to AI agents.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
query: Search term (e.g. "restaurant", "booking", "delivery")
|
|
138
|
+
category: Filter by category (optional)
|
|
139
|
+
"""
|
|
140
|
+
conn = _get_db()
|
|
141
|
+
q = f"%{query.lower()}%"
|
|
142
|
+
|
|
143
|
+
if category:
|
|
144
|
+
rows = conn.execute("""
|
|
145
|
+
SELECT id, business_name, description, category, capabilities_count, website
|
|
146
|
+
FROM interfaces
|
|
147
|
+
WHERE (LOWER(business_name) LIKE ? OR LOWER(description) LIKE ?)
|
|
148
|
+
AND LOWER(category) LIKE ?
|
|
149
|
+
ORDER BY business_name LIMIT 20
|
|
150
|
+
""", (q, q, f"%{category.lower()}%")).fetchall()
|
|
151
|
+
else:
|
|
152
|
+
rows = conn.execute("""
|
|
153
|
+
SELECT id, business_name, description, category, capabilities_count, website
|
|
154
|
+
FROM interfaces
|
|
155
|
+
WHERE LOWER(business_name) LIKE ? OR LOWER(description) LIKE ?
|
|
156
|
+
ORDER BY business_name LIMIT 20
|
|
157
|
+
""", (q, q)).fetchall()
|
|
158
|
+
|
|
159
|
+
results = [dict(r) for r in rows]
|
|
160
|
+
return {"query": query, "results_count": len(results), "businesses": results}
|
|
161
|
+
|
|
162
|
+
@mcp.tool()
|
|
163
|
+
async def get_business_capabilities(business_id: str) -> dict:
|
|
164
|
+
"""Get all capabilities of a registered business.
|
|
165
|
+
|
|
166
|
+
Returns the full spec including all available actions
|
|
167
|
+
an agent can take with this business.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
business_id: Business ID (from search_businesses)
|
|
171
|
+
"""
|
|
172
|
+
conn = _get_db()
|
|
173
|
+
row = conn.execute(
|
|
174
|
+
"SELECT * FROM interfaces WHERE id = ?", (business_id,)
|
|
175
|
+
).fetchone()
|
|
176
|
+
|
|
177
|
+
if not row:
|
|
178
|
+
return {"error": f"Business '{business_id}' not found"}
|
|
179
|
+
|
|
180
|
+
spec = json.loads(row["spec_json"])
|
|
181
|
+
return {
|
|
182
|
+
"business_id": business_id,
|
|
183
|
+
"business": spec.get("business", {}),
|
|
184
|
+
"capabilities": spec.get("capabilities", []),
|
|
185
|
+
"auth": spec.get("auth", {}),
|
|
186
|
+
"pricing": spec.get("pricing", {}),
|
|
187
|
+
"contact": spec.get("contact", {}),
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@mcp.tool()
|
|
191
|
+
async def fetch_remote_spec(url: str) -> dict:
|
|
192
|
+
"""Fetch an Agent Interface spec from a remote URL.
|
|
193
|
+
|
|
194
|
+
Businesses can host their spec at a well-known URL
|
|
195
|
+
(e.g. example.com/.well-known/agent-interface.json).
|
|
196
|
+
This tool fetches and validates it.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
url: URL to the Agent Interface spec JSON
|
|
200
|
+
"""
|
|
201
|
+
async with httpx.AsyncClient(timeout=15) as client:
|
|
202
|
+
resp = await client.get(url)
|
|
203
|
+
resp.raise_for_status()
|
|
204
|
+
spec = resp.json()
|
|
205
|
+
|
|
206
|
+
errors = validate_spec(spec)
|
|
207
|
+
business = spec.get("business", {})
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
"url": url,
|
|
211
|
+
"valid": len(errors) == 0,
|
|
212
|
+
"errors": errors if errors else None,
|
|
213
|
+
"business_name": business.get("name", "Unknown"),
|
|
214
|
+
"capabilities_count": len(spec.get("capabilities", [])),
|
|
215
|
+
"spec": spec if len(errors) == 0 else None,
|
|
216
|
+
"hint": "Use register_business to add this to your local directory." if not errors else None,
|
|
217
|
+
}
|