A correctness release for the three by-URN reads, plus a dependency and Go toolchain rollup.
Upgrade if any consumer relies on GetEntity, GetGlossaryTerm or GetDataProduct returning an error for an entity that does not exist. Before this release those three reads silently reported nonexistent entities as found.
Bug Fixes
Missing entities were reported as found (#204, #205)
GetEntity, GetGlossaryTerm and GetDataProduct decided an entity was missing by testing whether the GraphQL response echoed an empty URN. Against a real DataHub that test never fires — the entity resolvers hydrate a stub from the key aspect, returning the URN that was asked for, a name derived from it, no GraphQL error, and every real aspect null.
Verified against DataHub v1.6.0:
glossaryTerm(urn: "urn:li:glossaryTerm:Qa1605Nonexistent")
-> {"urn":"urn:li:glossaryTerm:Qa1605Nonexistent","exists":false,"name":"Qa1605Nonexistent","properties":null}
dataProduct(urn: "urn:li:dataProduct:qa-1605-nonexistent")
-> {"urn":"urn:li:dataProduct:qa-1605-nonexistent","properties":null}
A caller following the documented error-on-missing contract got a stub back and could not tell it from a real entity that happens to be undocumented. The glossary-term stub was the most convincing: its name is the URN's id segment, which is exactly what a real term's name usually is.
Each read now uses the signal its entity type actually offers, following the rule GetGlossaryNodeChildren already used:
| Read | Signal |
|---|---|
GetEntity |
exists, selected inside each inline fragment — the field lives on the concrete types, not on the Entity interface |
GetGlossaryTerm |
exists on the term |
GetDataProduct |
properties == nil — DataProduct has no exists field, and a product cannot be created without dataProductProperties |
GetEntityQuery also gained GlossaryTerm and GlossaryNode fragments, since rawAspectReadTypes routes those URNs through GetEntity for tag enrichment and both types carry exists.
Behaviour change: these three reads now return ErrNotFound where they previously returned a populated struct and a nil error. Code that treated a successful return as proof of existence will start seeing errors it did not see before — that is the fix, but it is a visible change at the call site.
Known limitation: Domain and Tag are still indistinguishable from their stubs. Neither type has an exists field in any DataHub schema version, and neither has a properties aspect that is mandatory at creation, so there is no honest absence signal to substitute. GetEntity on a nonexistent domain or tag URN still returns a stub.
Compatibility: unchanged. Only a definitive exists: false means absent — a DataHub version that omits the field leaves the pointer nil and the entity still stands, so older servers behave exactly as they did before.
Security
The Go toolchain moved from go1.26.4 to go1.26.8, clearing four called standard-library advisories that govulncheck flags on the previous toolchain (all fixed in go1.26.6):
| Advisory | Issue | Reached via |
|---|---|---|
| GO-2026-6218 | Quadratic resolvePath in net/url |
client.doRequest → http.Client.Do |
| GO-2026-6090 | Post-handshake message limit in crypto/tls |
client.doRequest → tls.Conn.Read |
| GO-2026-5972 | encoding/asn1 recursion depth |
extensions.LoggingMiddleware.After |
| GO-2026-5026 | ASCII-only Punycode labels in x/net/idna |
net/http |
Released binaries and container images are built with go1.26.8. Library consumers get the fix by building with go1.26.6 or newer — the toolchain directive in go.mod requests it, but your own build's toolchain is what ships in your binary.
Dependencies
| Dependency | From | To |
|---|---|---|
github.com/modelcontextprotocol/go-sdk |
v1.6.1 | v1.7.0 |
golang.org/x/sync (indirect, new) |
— | v0.20.0 |
golang.org/x/time (indirect, new) |
— | v0.15.0 |
github/codeql-action/* |
v4.37.3 | v4.37.4 |
ossf/scorecard-action |
v2.4.3 | v2.4.4 |
docker/login-action |
v4.4.0 | v4.6.0 |
docker/setup-buildx-action |
v4.2.0 | v4.3.0 |
anchore/sbom-action/download-syft |
v0.24.0 | v0.24.2 |
Supersedes Dependabot PRs #196, #197, #198, #201, #202, #203.
Unchanged
No changes to the tool surface: still 12 tools (9 read, 3 write). No config, environment variable, or MCP schema changes. Minimum supported DataHub stays v1.3.x, with the full feature set at v1.4.x+; queries are validated against the v1.5.0.1 schema and the fix was verified against a live v1.6.0.
Full changelog: v1.15.0...v1.15.1
Installation
Claude Desktop (macOS/Windows)
Download the .mcpb bundle for your platform and double-click to install:
- macOS Apple Silicon (M1/M2/M3/M4):
mcp-datahub_1.15.1_darwin_arm64.mcpb - macOS Intel:
mcp-datahub_1.15.1_darwin_amd64.mcpb - Windows:
mcp-datahub_1.15.1_windows_amd64.mcpb
Homebrew (macOS)
brew install txn2/tap/mcp-datahubClaude Code CLI
claude mcp add datahub \
-e DATAHUB_URL=https://your-datahub.example.com/api/graphql \
-e DATAHUB_TOKEN=your-token \
-- mcp-datahubGo library
go get github.com/txn2/mcp-datahub@v1.15.1Docker
docker pull ghcr.io/txn2/mcp-datahub:v1.15.1Verification
All release artifacts are signed with Cosign. Verify with:
cosign verify-blob --bundle mcp-datahub_1.15.1_linux_amd64.tar.gz.sigstore.json \
mcp-datahub_1.15.1_linux_amd64.tar.gz