Skip to content

feat: deployment story (Docker, remote MCP) + self-sufficient agent o… - #11

Open
dimittal wants to merge 2 commits into
mainfrom
feat/deployment-and-agent-onboarding
Open

feat: deployment story (Docker, remote MCP) + self-sufficient agent o…#11
dimittal wants to merge 2 commits into
mainfrom
feat/deployment-and-agent-onboarding

Conversation

@dimittal

@dimittal dimittal commented Aug 8, 2026

Copy link
Copy Markdown

…nboarding

Addresses user feedback that MCP connection details were unobtainable and that the MCP surface alone was not enough for an agent to author a brain.

Connection details

  • open-index serve printed http://0.0.0.0:8080/mcp — a bind address, not something any client can connect to. It now advertises reachable addresses (loopback + LAN), masks the token, and names the exact next command.
  • Add open-index mcp-config to emit an agent-ready config block for local (stdio) or remote (HTTP) brains, as JSON or a claude mcp add one-liner. Accepts host:port or a full URL and appends /mcp; absolutizes brain paths so a relative --brain . can't resolve against the agent's cwd. Does not open the search backend, so it works when the cluster is down.
  • Add serve --public-url for proxied/tunnelled deployments.

Backend selection

  • expand_env only ever reached OpenSearch credentials, so search.backend could only be changed by editing brain.yaml. Add OPEN_INDEX_SEARCH_BACKEND, OPEN_INDEX_OPENSEARCH_HOSTS/INDEX and OPEN_INDEX_DB_PATH overrides, validated with a clear error. Empty values (how compose passes unset vars) don't override.

Docker

  • Dockerfile (non-root, brain mounted not baked), compose with mutually exclusive sqlite / opensearch profiles plus an optional ui profile, .env.example, and an entrypoint that fails fast on a missing brain.yaml, waits for OpenSearch, and reconciles file-backed entities before serving.

Agent onboarding

  • create_doc_type had no relationships parameter, so an agent could not declare a relationship vocabulary over MCP at all.
  • Rewrite navigation_guidelines() to be self-contained: the model, the <doc_type>:<slug> id convention, worked call shapes, the full field-spec vocabulary, the storage policy, and per-doc_type field detail. For a remote brain this is the only documentation an agent ever sees.
  • Add a bootstrap section for empty brains, and honour read_only so a read-only endpoint stops advertising write tools it doesn't expose.
  • Errors now teach: unknown doc_type returns known_doc_types, a bad id shows the convention, schema failures report known_fields. Entity() was built outside the try block, so a malformed id escaped as a raw pydantic error.

Docs

  • New docs/deployment.md covering all three deployment paths, per-client config locations, a verification curl, troubleshooting, and connectors (the other MCP direction). README rewritten around it.

Tests

  • 221 passing, up from 86. 100% line coverage on every changed module (brain, cli, config, mcp_config, mcp_server, scaffold); cli.py was at 0%.

dimittal and others added 2 commits August 8, 2026 14:14
…nboarding

Addresses user feedback that MCP connection details were unobtainable and that
the MCP surface alone was not enough for an agent to author a brain.

Connection details
- `open-index serve` printed `http://0.0.0.0:8080/mcp` — a bind address, not
  something any client can connect to. It now advertises reachable addresses
  (loopback + LAN), masks the token, and names the exact next command.
- Add `open-index mcp-config` to emit an agent-ready config block for local
  (stdio) or remote (HTTP) brains, as JSON or a `claude mcp add` one-liner.
  Accepts `host:port` or a full URL and appends /mcp; absolutizes brain paths so
  a relative `--brain .` can't resolve against the agent's cwd. Does not open
  the search backend, so it works when the cluster is down.
- Add `serve --public-url` for proxied/tunnelled deployments.

Backend selection
- `expand_env` only ever reached OpenSearch credentials, so `search.backend`
  could only be changed by editing brain.yaml. Add OPEN_INDEX_SEARCH_BACKEND,
  OPEN_INDEX_OPENSEARCH_HOSTS/INDEX and OPEN_INDEX_DB_PATH overrides, validated
  with a clear error. Empty values (how compose passes unset vars) don't
  override.

Docker
- Dockerfile (non-root, brain mounted not baked), compose with mutually
  exclusive `sqlite` / `opensearch` profiles plus an optional `ui` profile,
  .env.example, and an entrypoint that fails fast on a missing brain.yaml,
  waits for OpenSearch, and reconciles file-backed entities before serving.

Agent onboarding
- `create_doc_type` had no `relationships` parameter, so an agent could not
  declare a relationship vocabulary over MCP at all.
- Rewrite `navigation_guidelines()` to be self-contained: the model, the
  `<doc_type>:<slug>` id convention, worked call shapes, the full field-spec
  vocabulary, the storage policy, and per-doc_type field detail. For a remote
  brain this is the only documentation an agent ever sees.
- Add a bootstrap section for empty brains, and honour read_only so a read-only
  endpoint stops advertising write tools it doesn't expose.
- Errors now teach: unknown doc_type returns known_doc_types, a bad id shows the
  convention, schema failures report known_fields. Entity() was built outside
  the try block, so a malformed id escaped as a raw pydantic error.

Docs
- New docs/deployment.md covering all three deployment paths, per-client config
  locations, a verification curl, troubleshooting, and connectors (the other
  MCP direction). README rewritten around it.

Tests
- 221 passing, up from 86. 100% line coverage on every changed module
  (brain, cli, config, mcp_config, mcp_server, scaffold); cli.py was at 0%.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Conflict was in mcp_server.py's put_entity: main added provenance/validity
while this branch added teaching error messages. Both are kept.

Resolution
- Merge both docstrings: the Args-style reference from this branch, plus main's
  guidance on attributing inferred claims and on world-time vs assertion-time.
- Build Provenance objects before constructing the Entity, so a malformed
  attribution block reports as "invalid provenance" instead of surfacing as a
  confusing schema-field error with an irrelevant known_fields list.
- Keep the teaching handlers (unknown doc_type -> known_doc_types, bad id ->
  the convention, missing edge target -> an example).

Bug found while verifying the merge (pre-existing on main, not from this merge)
- put_entity annotated related_to as list[dict[str, str]] while its body reads a
  nested "provenance" dict from each edge. The MCP SDK builds the tool's input
  schema from that annotation, so per-edge provenance was rejected at argument
  validation before the body ever ran — the feature was unreachable over MCP.
  Widened to list[dict[str, Any]]. main's provenance tests only exercise
  Entity.from_dict directly, which is why this was not caught.

Tests
- 287 passing. Added MCP-boundary coverage for provenance (entity, per-edge,
  validity, malformed blocks), search trust/time filters and provenance_report,
  index error reporting, and field-type validation.
- 100% line coverage on brain, cli, config, mcp_config, mcp_server, models,
  scaffold and schema.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant