Skip to content

Expose configuration#20

Merged
themartto merged 7 commits into
devfrom
expose-configuration
May 8, 2026
Merged

Expose configuration#20
themartto merged 7 commits into
devfrom
expose-configuration

Conversation

@themartto
Copy link
Copy Markdown
Contributor

@themartto themartto commented May 7, 2026

Summary by CodeRabbit

  • New Features

    • Added REST API endpoints (/api/config, /api/models, /api/skills, /api/tools, /api/mcp-servers) to access server configuration and status information.
    • Server now reports detailed connection and status information for external services.
  • Documentation

    • Updated configuration guides with expanded provider-specific examples and unified endpoint documentation.

themartto added 4 commits May 6, 2026 20:24
…_meta

Adds GET /api/config, /api/models, /api/skills, /api/tools, /api/mcp-servers
endpoints (replacing /models). MCP connection status is tracked at startup
and surfaced per-server. The same data is included in InitializeResponse._meta
alongside the existing models entry.
@themartto
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds MCP server status tracking and REST API endpoints to expose configuration, models, skills, tools, and server metadata. The changes flow from new serializable data structures through status collection during tool loading, agent state initialization, and finally HTTP endpoint handlers, alongside documentation and Docker deployment updates.

Changes

MCP Server Status Exposure & REST API

Layer / File(s) Summary
Data Shapes & Public Config Views
src/config/types.rs, src/mcp/mod.rs, src/config/mod.rs
New ProviderModels, ModelsInfo, and McpServerInfo structs provide JSON-safe public views of configuration; McpServerStatus struct captures per-server connection state; AppConfig gains models_info(), to_public_json(), and mcp_servers_info() methods to produce redacted public-facing data.
MCP Tool Loading & Status Capture
src/mcp/mod.rs, src/tools/mod.rs
load_mcp_tools() now returns (handlers, Vec<McpServerStatus>) with per-server connection metadata and error tracking; SystemToolExecutor::build() returns tuple with executor and captured MCP server statuses.
Agent State & Initialization Metadata
src/acp/mod.rs
AgentState adds mcp_statuses field for persistence; AgentState::new initializes via SystemToolExecutor::build; initialization response populates metadata with serialized models, MCP server info, and available tools; NewSessionRequest resolves session config from client-provided meta["model"].
REST API Endpoints & Handlers
src/transport/ws.rs
New GET endpoints /api/config, /api/models, /api/skills, /api/tools, /api/mcp-servers return JSON derived from AgentState and AppConfig; startup logging advertises API availability.
Deployment & Documentation
Dockerfile, README.md
Dockerfile copies default config.toml to container home directory; README updated with unified WebSocket description, expanded provider-specific config examples with Anthropic/Gemini settings, MCP server configuration stubs, REST API endpoint documentation, and refined project structure listing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • weirdstuff-dev/openheim#18: Introduces core MCP server configuration and client connection support, providing the underlying MCP infrastructure that this PR extends with status tracking and REST API exposure.

Poem

🐰 Status quo hops along today,
REST paths guide the wayward way,
MCP servers stand so proud and tall,
Exposed to endpoints, one and all!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title "Expose configuration" is vague and generic. While it relates to the PR's objective of exposing configuration data, it uses a non-descriptive term that does not convey the specific primary change—adding REST API endpoints to surface configuration, models, skills, tools, and MCP server status information. Consider a more specific title such as "Add REST API endpoints for configuration and system metadata" or "Expose configuration via API endpoints and initialize response metadata."
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
Dockerfile (1)

49-49: ⚡ Quick win

Set explicit owner for copied config file.

At Line 49, add --chown=openheim:openheim to ensure the copied config file is owned by the runtime user. Without this flag, Docker preserves host file ownership, which can cause permission issues if the application needs to modify the config.

Proposed change
-COPY config.toml /home/openheim/.openheim/config.toml
+COPY --chown=openheim:openheim config.toml /home/openheim/.openheim/config.toml
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile` at line 49, Update the Dockerfile COPY instruction that copies
the config file (the line containing "COPY config.toml
/home/openheim/.openheim/config.toml") to set explicit ownership by adding the
--chown=openheim:openheim flag so the file is owned by the runtime user; modify
that COPY to use --chown=openheim:openheim before the source path.
src/mcp/mod.rs (1)

13-25: MCP connection status is a startup-time snapshot — stale after process start.

McpServerStatus is populated once in load_mcp_tools and stored immutably in AgentState::mcp_statuses. A server that was down at startup (connected: false) will never flip to connected: true, and a server that was up but later disconnects will still show as connected: true. The /api/mcp-servers endpoint and InitializeResponse._meta will both serve potentially stale data indefinitely.

Consider whether a background health-check loop (re-running connect_server for failed entries at startup) or a lazily-refreshed status would better serve consumers of the /api/mcp-servers endpoint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp/mod.rs` around lines 13 - 25, McpServerStatus is only set once in
load_mcp_tools and stored in AgentState::mcp_statuses, so `/api/mcp-servers` and
InitializeResponse._meta serve stale startup snapshots; fix by adding periodic
or on-demand refresh logic: implement a background health-check task (spawned at
startup) that re-runs connect_server for entries in AgentState::mcp_statuses (or
specifically retries entries with connected == false) and updates the
McpServerStatus entries atomically, or add lazy refresh when the
/api/mcp-servers handler is called to re-check and refresh individual
McpServerStatus before returning; update AgentState::mcp_statuses mutation logic
accordingly and ensure synchronization (locks/async-safe updates) so the new
connected/tool_count/error fields reflect runtime state.
src/tools/mod.rs (1)

37-47: ⚖️ Poor tradeoff

build return type change is untested.

The existing test suite covers new, register_builtins, and unknown-tool execution, but nothing exercises the updated build path or verifies that mcp_statuses is correctly propagated. A minimal async test would guard against future regressions here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tools/mod.rs` around lines 37 - 47, The build function's changed return
type (now returning (Self, Vec<crate::mcp::McpServerStatus>)) is untested; add a
minimal async test that calls tools::build with a small mcp_configs map
(exercising crate::mcp::load_mcp_tools path), asserts that the returned executor
behaves like one created by tools::new/register_builtins (e.g., can execute a
known builtin or unknown-tool behavior via executor.register/execute) and also
verifies the Vec<McpServerStatus> is returned and has expected content or
length; reference tools::build, tools::new, tools::register_builtins,
crate::mcp::load_mcp_tools, executor.register and McpServerStatus when locating
where to add the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/acp/mod.rs`:
- Around line 91-93: The _meta["mcp_servers"] entry is being populated with
config-only data from mcp_servers_info(), which differs from the REST payload
shape; change the meta population to serialize the runtime status data in
state_init.mcp_statuses (or convert it into the same Vec<McpServerStatus> shape
used by GET /api/mcp-servers) instead of using mcp_servers_info(), so
InitializeResponse._meta["mcp_servers"] matches the runtime structure returned
by the API.

In `@src/config/types.rs`:
- Around line 102-114: mcp_servers_info currently sets transport = "http"
whenever cfg.command is None, which mislabels entries where both cfg.command and
cfg.url are None; change the logic in mcp_servers_info (function name) to branch
three-ways: if cfg.command.is_some() => transport "stdio" with command, else if
cfg.url.is_some() => transport "http" with url, else => set transport to
something like "unknown" (or empty) and leave both command and url None; apply
the identical three-way fix to the matching if/else in load_mcp_tools in
src/mcp/mod.rs so misconfigured entries are not reported as "http".
- Around line 81-100: The current to_public_json silently returns Value::Null on
serialization failure because it uses
serde_json::to_value(self).unwrap_or_default(), skipping all redaction logic;
change to propagate the serialization error instead by updating to_public_json
to return Result<serde_json::Value, serde_json::Error> (or another appropriate
error type), replace unwrap_or_default with a fallible call to
serde_json::to_value(self)? and return the Err on failure, keep the redaction
logic for "providers" -> "api_key" and "mcp_servers" -> "env" unchanged, and
update all callers to handle the Result (or log the error at call sites) so
serialization failures are not silently swallowed.

In `@src/transport/ws.rs`:
- Around line 59-63: The new REST routes in src/transport/ws.rs (/api/config,
/api/models, /api/skills, /api/tools, /api/mcp-servers) lack authentication and
CORS; add a middleware layer that enforces a simple bearer-token check (read
token from config/env) and return 401 for missing/invalid tokens, and apply it
to the Router that registers config_handler, models_handler, skills_handler,
tools_handler, and mcp_servers_handler; additionally add a CORS layer
(tower_http::cors::CorsLayer) configured to allow the intended browser origins,
methods (GET), and headers (Authorization), and attach it to the same Router so
browser fetch/XHR can succeed while requests from other origins remain
controlled.

---

Nitpick comments:
In `@Dockerfile`:
- Line 49: Update the Dockerfile COPY instruction that copies the config file
(the line containing "COPY config.toml /home/openheim/.openheim/config.toml") to
set explicit ownership by adding the --chown=openheim:openheim flag so the file
is owned by the runtime user; modify that COPY to use --chown=openheim:openheim
before the source path.

In `@src/mcp/mod.rs`:
- Around line 13-25: McpServerStatus is only set once in load_mcp_tools and
stored in AgentState::mcp_statuses, so `/api/mcp-servers` and
InitializeResponse._meta serve stale startup snapshots; fix by adding periodic
or on-demand refresh logic: implement a background health-check task (spawned at
startup) that re-runs connect_server for entries in AgentState::mcp_statuses (or
specifically retries entries with connected == false) and updates the
McpServerStatus entries atomically, or add lazy refresh when the
/api/mcp-servers handler is called to re-check and refresh individual
McpServerStatus before returning; update AgentState::mcp_statuses mutation logic
accordingly and ensure synchronization (locks/async-safe updates) so the new
connected/tool_count/error fields reflect runtime state.

In `@src/tools/mod.rs`:
- Around line 37-47: The build function's changed return type (now returning
(Self, Vec<crate::mcp::McpServerStatus>)) is untested; add a minimal async test
that calls tools::build with a small mcp_configs map (exercising
crate::mcp::load_mcp_tools path), asserts that the returned executor behaves
like one created by tools::new/register_builtins (e.g., can execute a known
builtin or unknown-tool behavior via executor.register/execute) and also
verifies the Vec<McpServerStatus> is returned and has expected content or
length; reference tools::build, tools::new, tools::register_builtins,
crate::mcp::load_mcp_tools, executor.register and McpServerStatus when locating
where to add the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f90812e2-c9dc-4139-b294-73213942114d

📥 Commits

Reviewing files that changed from the base of the PR and between 65d2f30 and 73bf574.

📒 Files selected for processing (8)
  • Dockerfile
  • README.md
  • src/acp/mod.rs
  • src/config/mod.rs
  • src/config/types.rs
  • src/mcp/mod.rs
  • src/tools/mod.rs
  • src/transport/ws.rs

Comment thread src/acp/mod.rs Outdated
Comment thread src/config/types.rs
Comment thread src/config/types.rs
Comment thread src/transport/ws.rs
@themartto themartto marked this pull request as ready for review May 8, 2026 05:10
@themartto themartto merged commit 1834a60 into dev May 8, 2026
1 check was pending
@coderabbitai coderabbitai Bot mentioned this pull request May 12, 2026
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