Skip to main content

Keturah

A uniform, MCP-bridgeable manifest of a product's LLM-consumable interfaces.

Keturah lets any family product — library or service — answer one question: what can an LLM call here, and how? Each interface is a Capability (name, description, JSON-Schema input/output); a Manifest bundles them with the product and version. The name is biblical ("incense / that which is offered up") — the catalog of what each product offers.

There is already a standard for this — Model Context Protocol (MCP) — and Keturah does not replace it. Manifest.to_mcp() projects a manifest onto MCP's tools/list shape, so a real MCP server is a thin adapter over a Keturah manifest rather than a parallel definition. Keturah exists because the family is a mix of libraries and services, and because manifests should be built from the seam contracts a product already enforces (Deborah's plan schema, Milcah's specialist request/result, Mahalath's match, Galeed's events) so the manifest and the contract never drift.

from keturah import manifest, capability, Registry, MANIFEST_SCHEMA_VERSION

m = manifest(
    "tirzah",
    version="1.3.0",
    capabilities=[
        capability(
            "ask",
            "Answer a question over Tirzah's memory.",
            input_schema={
                "type": "object",
                "properties": {"query": {"type": "string"}},
                "required": ["query"],
            },
            output_schema={
                "type": "object",
                "properties": {
                    "answer": {"type": "string"},
                    "traceId": {"type": "string"},
                },
            },
            tags=["qa", "memory"],
        ),
        capability(
            "capabilities",
            "List this product's interfaces.",
            kind="resource",
            tags=["discovery"],
        ),
        capability(
            "system_prompt",
            "Default system prompt for agents using this product.",
            kind="prompt",
        ),
    ],
)

m.schema_version          # MANIFEST_SCHEMA_VERSION ("1.0")
m.to_dict()               # full manifest (descriptions + schemas)
m.to_mcp()                # MCP tools/list — tools only; includes outputSchema
m.resources()             # kind="resource" capabilities
m.prompts()               # kind="prompt" capabilities

A product typically exposes this as capabilities() and, where it is a service, a GET /api/capabilities endpoint (with ?format=mcp for the MCP view).

Registry (federated discovery)

reg = Registry([m, other_product_manifest])

reg.find("ask")                    # first (product, capability) match
reg.find("tirzah.ask")             # namespaced — same form to_mcp() emits
reg.find("ask", product="tirzah")  # explicit product wins
reg.find_all("ask")                # every product exposing that tool name

reg.tools()                        # all kind="tool"
reg.resources()                    # all kind="resource"
reg.prompts()                      # all kind="prompt"
reg.with_tag("planner")

reg.to_mcp()                       # union tools/list; names are product.tool

MCP projection

Capability.to_mcp_tool() / Manifest.to_mcp() / Registry.to_mcp() emit the MCP tools/list shape:

Keturah field MCP field
name name (Registry namespaces as product.tool)
description description
input_schema inputSchema
output_schema outputSchema (omitted when unset)

Only kind="tool" entries appear in to_mcp(). Resources and prompts stay on the Keturah surface (resources() / prompts()); a real MCP server can map them to MCP prompts/resources resources separately via keturah.mcp.run_stdio_server.

Manifest validation requires schema_version equal to MANIFEST_SCHEMA_VERSION so consumers can version-gate.

Review

A point-in-time functional + code review of 0.4.0 is in docs/review-2026-08-08.md; findings actioned in 0.5.0 (Stage 0 field validation, no . in capability names, MCP parse errors, to_mcp collision guard, band_for non-finite).

Develop

Works the same on native Linux and WSL — stdlib-only, no platform-specific steps.

pip install -e ".[dev]" && pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

keturah-0.5.0.tar.gz (34.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

keturah-0.5.0-py3-none-any.whl (27.2 kB view details)

Uploaded Python 3

File details

Details for the file keturah-0.5.0.tar.gz.

File metadata

  • Download URL: keturah-0.5.0.tar.gz
  • Upload date:
  • Size: 34.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for keturah-0.5.0.tar.gz
Algorithm Hash digest
SHA256 d3be85e51e0f73fb695c30f64a72c729a07185f41762e71a480e61a6363f8bfe
MD5 b583c176d2540168a20683599d48bdc7
BLAKE2b-256 4479143c0716a39e42d6130e8b9c864684578570b4ec86c3f8aba2ae1ed90463

See more details on using hashes here.

File details

Details for the file keturah-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: keturah-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 27.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for keturah-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 25d9ee6f967bcbfc41cf0142fbd423aac2ebbb1c474c06ee2b83394ef8bec664
MD5 79858f78a8aebc1969ce344a097ebc76
BLAKE2b-256 94c220439177aa3a655b7e1e5c7a041ea85b5e158a8e34c331b7d02c1d9ad8fd

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.1

2 files

This release

0.5.0 This release

2 files

0.4.0

2 files

0.3.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page