v0.6.0: Agent-first protocol — MCP server, REST API, 6 tools#4
v0.6.0: Agent-first protocol — MCP server, REST API, 6 tools#4vigneshnarayanaswamy merged 18 commits intomainfrom
Conversation
Create the tools package with all 16 Pydantic v2 models covering 6 tool contracts (record, query, investigate, trace, changelog, discover) plus 4 shared types (ModelSummary, EventSummary, EventDetail, DependencyNode). These schemas are the single source of truth for MCP, REST API, and CLI. 72 tests covering all fields, defaults, JSON round-trip, and JSON Schema export. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the query tool with structured filters (model_type, owner, status), case-insensitive text search on name/purpose, and pagination. Includes _model_to_summary helper for reuse by the discover tool. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the discover tool for bulk model ingestion from inline data, JSON files, or connectors. Inline and file sources convert dicts to DataNodes and leverage ledger.add() for content-hash dedup and ledger.connect() for auto-linking dependencies. Connector source raises NotImplementedError pending SDK-direct usage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the changelog tool with time range filtering (since/until), model_name and event_type filters, pagination, and newest-first ordering. Includes 15 tests covering all specified behaviors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Re-exports changelog, discover, investigate, query, record, and trace from model_ledger.tools so consumers can import tool functions directly from the package. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JsonFileLedgerBackend stores models, snapshots, and tags as indented JSON files in a directory tree. Implements full LedgerBackend protocol including sorted snapshot listing and tag-based resolution. 23 tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a FastAPI app at model_ledger.rest.app with endpoints for all 6 agent protocol tools (record, discover, investigate, query, trace, changelog) plus /overview. ModelNotFoundError maps to HTTP 404. Adds rest-api optional dependency and E402 suppression for tests using pytest.importorskip. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FastMCP server wrapping all tool functions (discover, record, investigate, query, trace, changelog) with primitive-typed parameters for MCP compat. Three resources: ledger://overview, ledger://schema, ledger://backends. Includes create_server() factory and main() CLI entry point. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Repositions model-ledger as a fundamental model inventory (not MRM-specific). Adds agent-first messaging, MCP/REST docs, tool protocol overview, JSON file backend, and updated install profiles. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Clear section hierarchy with progressive disclosure - Fix architecture diagram (add SDK layer between tools and backends) - Fix self-contained investigate example - Trim agent conversation (3 → 2 exchanges) - Collapse compliance/introspection into brief "Additional Capabilities" - Add positioning line vs MLflow/SageMaker/W&B - Remove "thin tools, thick descriptions" from public README (internal) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These docs reflect the old compliance-first positioning (v0.2-v0.3) and are superseded by the v0.6.0 README. Archived to second brain. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Ledger.add() now reads model_type/type from DataNode metadata (was only reading node_type, which nobody set) - investigate: skip internal events (depends_on, has_dependent, registered) and internal keys (_content_hash, upstream/downstream hashes) when merging metadata - query: extract platform from discovered payload, not just snapshot.source - demo: add model_type to all DataNode metadata Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a3fb8c0e75
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| def _resolve_backend(backend: str, path: str | None): | ||
| """Resolve a backend name to a backend instance.""" | ||
| if backend == "sqlite" and path: |
There was a problem hiding this comment.
Use sqlite backend even when --path is omitted
When backend is set to sqlite, _resolve_backend only returns a SQLiteLedgerBackend if path is truthy; otherwise it returns None, and both mcp_cmd and serve_cmd fall back to the default in-memory backend. Running model-ledger mcp --backend sqlite (or serve) without --path therefore silently loses persistence, which is a high-impact mismatch with the user-selected backend.
Useful? React with 👍 / 👎.
| if input.model_type is not None: | ||
| filters["model_type"] = input.model_type | ||
| if input.owner is not None: | ||
| filters["owner"] = input.owner | ||
| if input.status is not None: |
There was a problem hiding this comment.
Enforce platform filter in query tool
The query API exposes platform in QueryInput and the REST/MCP surface, but query() never applies input.platform in either backend filters or post-filtering. As a result, requests like platform="airflow" return models from other platforms, producing incorrect inventory slices for callers that rely on platform-scoped search.
Useful? React with 👍 / 👎.
| # ------------------------------------------------------------------ | ||
|
|
||
| def _model_path(self, name: str) -> Path: | ||
| return self._models_dir / f"{_sanitize(name)}.json" |
There was a problem hiding this comment.
Prevent filename collisions in JSON model storage
Model files are keyed by _sanitize(name), which replaces /, \\, and whitespace with _. Distinct model names can therefore map to the same filename (for example "a/b" and "a b"), causing one save to overwrite another and making reads by name/hash inconsistent. This is data-loss behavior in the new JSON backend.
Useful? React with 👍 / 👎.
| since_dt = datetime.fromisoformat(since) if since else None | ||
| until_dt = datetime.fromisoformat(until) if until else None |
There was a problem hiding this comment.
Handle invalid changelog date params as client errors
changelog_endpoint parses since/until with datetime.fromisoformat directly from query strings. Malformed values raise ValueError and currently bubble as 500 responses instead of a 4xx validation error, so bad client input is reported as a server failure.
Useful? React with 👍 / 👎.
Summary
model-ledger mcpstarts a stdio server with 6 tools + 3 resourcesmodel-ledger servestarts HTTP server with auto-generated OpenAPI docs--demoflag loads 7 sample models with events and dependenciesmcpandservewith--backend,--path,--demoflagsClaude Code integration
REST API for frontends
pip install model-ledger[rest-api] model-ledger serve --demo # OpenAPI docs at http://localhost:8000/docsTest plan
🤖 Generated with Claude Code