heinzel-acme-connectors
ACME's own connectors: how a company implements every Heinzelmännchen connector in its private plugin repository. Every adapter runs on dummy data and reaches it through one seam, shaped for a company MCP gateway with one local launcher per tool. Replace the seam and the adapters read your tools.
| Capability | Core protocol | What the dummy does | What a real company replaces |
|---|---|---|---|
calendar |
Calendar |
ACME's week: events with attendees and a video call, free/busy, create, move, cancel; respond is unsupported |
_backend.connect("calendar"), and the tool names in CONNECTORS |
mail |
Mail |
Nadia's mailbox: search, read, threads, drafts, labels; mail bodies in an untrusted envelope, one of them hostile; send_draft is unsupported |
_backend.connect("mail") |
documents (drive) |
Documents |
Adapter acme-connectors-docs: docs.acme.example links and doc-… ids, read only |
_backend.connect("docs") |
documents (wiki) |
Documents |
Adapter acme-connectors-wiki: wiki.acme.example links and page ids, read only |
_backend.connect("wiki") |
tracker |
Tracker |
The Checkout project CHK: read, create, claim (not atomic), move, comment, close; attach is unsupported |
_backend.connect("tracker"); an atomic claim needs a gateway tool that assigns only if unassigned |
chat |
Chat |
Two backends, chosen by acme-connectors.chat_backend: memory, Slack-like channels with messages, post, notify_self and ask_self; or command, which runs acme-chat for notify_self and ask_self only |
_backend.connect("chat"), or acme-connectors.chat_command set to your own chat command |
meetings |
Meetings |
Zoom-like meetings; only the recorded one has a transcript | _backend.connect("meetings") |
code-host |
CodeHost |
Merged pull requests of acme/acme-checkout |
_backend.connect("code-host") |
directory |
Directory |
Who reports to whom in Payments | _backend.connect("directory") |
ai-models |
AiModels (ADR 0159) |
ACME Fast and ACME Deep, dummy models that answer offline; one model switched off. Registered on a Core with the capability | AcmeModels.model: build a Pydantic AI model on your own HTTP client for your model gateway |
ACME keeps documents in two stores, so it ships two documents adapters. That is the pattern for any capability with
two sources: one adapter per source, each declaring with links the host of the addresses people open. Core 0.9.43
(ADR 0161) binds both (hz system config set capabilities.documents '["acme-connectors-docs", "acme-connectors-wiki"]'),
sends each link to the adapter whose links name its host, and fans a search out to both. An older Core binds one.
Everything is fictional: ACME at acme.example, org Payments, team Checkout, site Lisbon, and its people (Nadia Moreira, Tomas Leal, Priya Raman), in the week of 2 November 2026.
Pick them
ACME's company layer keeps binding its capabilities to the first-party plugins (GitHub, Google, Atlassian, Zoom;
src/heinzel_acme/_bindings.py), and its rehearsal uses those. This plugin is a separate worked example: installed,
it offers its connectors as alternatives you pick per capability, in the app (Settings, Connectors, "Which connector
serves what"; each change asks to restart and apply) or on the command line:
hz system config set capabilities.mail acme-connectors
hz system config set capabilities.documents acme-connectors-wiki
hz system config set acme-connectors.chat_backend command # chat through acme-chat
hz system config set acme-connectors.sign_in_state expired # show the expired sign-in
It never writes a binding and never overrides one: a binding you or a playbook set (hz setup acme writes
capabilities.code_host = "github" and the rest) stays as it is when this plugin is installed
(tests/integration/connectors_bindings_test.py). A capability nothing binds is served by its only installed adapter
(Core ADR 0055): without the first-party plugins that is this plugin for calendar, chat, code host, meetings and
tracker, which is what a demo wants; alongside them, it is so only for chat, which none of them provides.
Connected and signed in
hz system connector list and the app's connector page show the sign-in through a dummy SignInProvider
(_sign_in.py, ADR 0136). It reports one of three states, chosen by acme-connectors.sign_in_state: signed in as
nadia@acme.example, signed out, or expired, with the problem in words. sign_in reports a made-up consent page at
login.acme.example, and sign_out forgets the sign-in, both for the running process. An offline health check
(launchers and sign-in) runs in hz system doctor. A live check starts every connector and checks its tools, on
hz system connector test acme-connectors. A real plugin asks its gateway launcher instead.
The seams
src/heinzel_acme_connectors/:
_backend.pyis the one file a company replaces. Every gateway adapter reaches data only throughconnect(name).call(tool, arguments), which returns Core'sMcpResult(data,text,untrusted, the parts the gateway marked, andcut). Each connector inCONNECTORSnames its local stdio launcher (one per connector, holding the sign-in, so the plugin holds no secret), the tools its adapter calls (McpTool: name, read or write, aliases), the untrusted-content markers its answers carry, and its modes: docs, wiki, meetings, code host and directory are read only, so a write tool is refused there. Todayconnectserves the dummy data throughStandInConnector, which checks that every tool exists and takes the markers off with Core's own rules. With Core's MCP helper (heinzel.connectors.mcp, ADR 0159)connectreturnsMcpConnector(launcher, tools=..., markers=..., modes=...)instead; the module docstring shows the code, andMcpConnector.in_processruns an MCP server object in a company's own adapter tests.- Untrusted content: a gateway marks text people wrote inline (
«untrusted-data»…«/untrusted-data»), read conservatively from the first marker to the last, or in an envelope with a fresh id (<untrusted-mail-data-UUID>…</untrusted-mail-data-UUID>, any kind of data), which text inside can't close. The markers come off and any stray one is removed, and_text.pypasses every string through Core'sclean_text. What the text says stays data, never an instruction, so the adapters need nountrustedlist of their own. _chat_command.pyandacme_chat.py: the chat command backend. The adapter runs the command with an argument list (never a shell), a timeout, nothing on stdin, and only the basics of hz's environment (PATH,HOME,LANGand its ownACME_CHAT_*), not the keys hz may hold. It reads both streams as they come: at most 64 KiB of stdout (more stops the command) and the last 4 KiB of stderr, so memory stays bounded however much the command writes. A non-zero exit, a timeout or bad JSON is a clear error.acme-chatis a made-up command (tell,question) whose answers come fromACME_CHAT_ANSWERor the file inACME_CHAT_ANSWERS, so it never blocks._compat.pyand_standins.py: what Core ships after 0.9.42 (ADR 0159, 0160, 0161)._compatuses Core's own classes where the installed Core has them, and exact copies from_standinswhere it doesn't (tests/unit/standins_test.pycompares them with Core's). With the minimum at that release, both files go.- One module per capability (
_mail.py,_calendar.py,_documents.py,_tracker.py,_chat.py,_meetings.py,_code_host.py,_directory.py,_ai_models.py) maps the gateway's JSON to Core's models; keep them and change the mapping where your gateway answers differently. _dummy.py: the in-memory servers and their fixtures. A real plugin deletes it.
Modes are honest: an adapter declares write only when one of its capability's write methods works, so the
documents adapters are read only. What a connector can't do is listed in unsupported (per instance for chat,
whose backend decides). A Core with ADR 0159 refuses those methods itself, before the call, with
NotSupportedError ("This mail connector can't send draft."); the reasons in the adapters' own refusals show only
on an older Core or when the method is called directly.
Make it your company's
- Copy this directory into your company's private plugin repository (no remote needed) and rename it.
- In
_backend.py, point each connector's launcher at your gateway's, list the tools it really has, and return the MCP client fromconnect. Delete_dummy.pyand the stand-in. - Set the hosts in
__init__.pyto your gateway's and your document stores', and adjustunsupportedand the modes to what your gateway can do. - Install it from the folder:
hz system plugin add /path/to/your-repo(Core 0.9.43 or later).
Requirements
- Heinzelmännchen 0.9.41 or later; tested on 0.9.42 and on the 0.9.43 bundle.
ai-models, the MCP helper, the chat self channel,unsupportedhandled by the kernel and two documents adapters at once need Core 0.9.43, which ships ADR 0159, 0160 and 0161; on an older Core the stand-ins keep the plugin working, withoutai-modelsand with one documents adapter bound. - Python 3.12 or later.
Tests (tests/unit, tests/integration) check each adapter against its Core protocol (signatures, honest modes,
unsupported, hosts), its behaviour on the dummy data, the chat command's timeout, bad JSON, failing exit and
bounded reading, and every capability bound through a kernel. tests/integration/conformance_test.py runs Core's
conformance kit with sample arguments for every read method, the check a company's own CI should copy; it is
skipped on a Core without the kit.
Metadata
Release files for heinzel-acme-connectors 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| heinzel_acme_connectors-0.4.0.tar.gz | 338.9 kB | With provenance | Details for heinzel_acme_connectors-0.4.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| heinzel_acme_connectors-0.4.0-py3-none-any.whl | Python 3 | none | any | Details for heinzel_acme_connectors-0.4.0-py3-none-any.whl |
Total release size: 389.1 kB
Release files / heinzel_acme_connectors-0.4.0.tar.gz
| Download URL | heinzel_acme_connectors-0.4.0.tar.gz |
|---|---|
| Size | 338.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
879e1d9cb885c94ec806c082461644fc38de900804be63fa2171663c309188d7
|
|
BLAKE2b-256 checksum How to use checksums |
432775a7b7652449bcba47293758090880c3df04ccd825ea38a4048a45d7ea27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logRelease files / heinzel_acme_connectors-0.4.0-py3-none-any.whl
| Download URL | heinzel_acme_connectors-0.4.0-py3-none-any.whl |
|---|---|
| Size | 50.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
454c1d2e0f5657c4963afd696d70672b7427cc309fd117bf96b6993dda15a28e
|
|
BLAKE2b-256 checksum How to use checksums |
db3b7103ca516f03b994afd65ada15225779e58a597e279f747c6688c14bb2eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logSecurity for heinzel-acme-connectors 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for heinzel_acme_connectors-0.4.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.