feat(standards): integrate auth-server via pinned spec (docs://spec) + auth recipe and template slice
- serve the pinned auth-server OpenAPI contract as the standards MCP resource docs://spec (no auth-server MCP bundle) - add Auth Integration recipe (14) and wire it into the registry, prompts, index, and nav - un-defer Auth Server in the library registry (spec/recipe pointers) - ship the opt-in template auth slice: interfaces/auth/ (placeholder + mergeable bearerAuth security.yaml) and AUTH_SERVER/JWT_SERVER env - rebuild bundle (13 modules, 44 components); template stays authless by default
This commit is contained in:
27
registry.py
27
registry.py
@@ -7,6 +7,7 @@ template code — before writing any infrastructure.
|
||||
|
||||
Resources:
|
||||
docs://index, docs://nav, docs://modules/{module} (from the base server)
|
||||
docs://spec (the pinned auth-server OpenAPI contract)
|
||||
registry://libraries (the structured catalog)
|
||||
registry://components (the template component index)
|
||||
|
||||
@@ -46,7 +47,8 @@ _INTAKE_TEXT = (
|
||||
"2. Axis 1 — resources: each resource, its fields, and relationships\n"
|
||||
" (or paste `openapi.yaml`).\n"
|
||||
"3. Axis 2 — pipelines: multi-step inputs? families + formats (or `none`).\n"
|
||||
"4. Auth needed now? (yes/no; auth is deferred — `py-jwt` only).\n"
|
||||
"4. Auth needed now? (yes/no). If yes, the auth-server service provides it —\n"
|
||||
" read `docs://spec` + `docs://modules/auth_integration` (no auth code to write).\n"
|
||||
"5. Integrations: Mongo / ingestion formats / email / LLM provider.\n\n"
|
||||
"Then: `build(app_name=..., resources=..., pipelines=..., auth=...)`.\n"
|
||||
)
|
||||
@@ -79,7 +81,10 @@ def _build_text(app_name: str, resources: str, pipelines: str, auth: str) -> str
|
||||
"4. Scaffold with `get_app_template()` (whole tree) or pull single "
|
||||
"files with `list_app_components()` and "
|
||||
"`get_app_component(kind, resource=..., family=...)`.\n"
|
||||
"5. Author only Tier C; keep Tier B as shipped.\n"
|
||||
"5. If auth is needed, read `docs://spec` (the auth-server contract) and "
|
||||
"`docs://modules/auth_integration`; declare `securitySchemes.bearerAuth` "
|
||||
"and `security` in your spec — do not write auth code.\n"
|
||||
"6. Author only Tier C; keep Tier B as shipped.\n"
|
||||
)
|
||||
|
||||
|
||||
@@ -114,6 +119,13 @@ class StandardsMCPServer(MCPServer):
|
||||
return {"error": "not_found", "path": str(path), "components": []}
|
||||
return json.loads(path.read_bytes())
|
||||
|
||||
def _spec(self) -> dict[str, Any]:
|
||||
"""Load the pinned OpenAPI contract (auth-server)."""
|
||||
path = Path(self.mcp_root) / "specs" / "auth-server.json"
|
||||
if not path.exists():
|
||||
return {"error": "not_found", "path": str(path)}
|
||||
return json.loads(path.read_bytes())
|
||||
|
||||
def _find_component(self, kind: str) -> dict[str, Any] | None:
|
||||
for entry in self._components().get("components", []):
|
||||
if entry.get("kind") == kind:
|
||||
@@ -183,6 +195,15 @@ class StandardsMCPServer(MCPServer):
|
||||
def components() -> dict[str, Any]:
|
||||
return self._components()
|
||||
|
||||
@self.app.resource("docs://spec")
|
||||
def spec() -> dict[str, Any]:
|
||||
"""Return the pinned auth-server OpenAPI contract.
|
||||
|
||||
Use this (instead of a live fetch) to learn the auth-server client
|
||||
contract when wiring authentication into an app.
|
||||
"""
|
||||
return self._spec()
|
||||
|
||||
@self.app.tool()
|
||||
def find_library(capability: str) -> list[dict[str, Any]]:
|
||||
"""Find internal libraries matching a capability keyword.
|
||||
@@ -211,6 +232,8 @@ class StandardsMCPServer(MCPServer):
|
||||
str(lib.get("import", "")),
|
||||
str(lib.get("purpose", "")),
|
||||
str(lib.get("use_instead_of", "")),
|
||||
str(lib.get("spec", "")),
|
||||
str(lib.get("recipe", "")),
|
||||
" ".join(lib.get("capabilities", [])),
|
||||
]
|
||||
).lower()
|
||||
|
||||
Reference in New Issue
Block a user