Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
result
result-*
.direnv/
/worktrees/
1 change: 1 addition & 0 deletions .graphifyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/worktrees/
17 changes: 17 additions & 0 deletions checks.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
];
};

withoutMcp = defaults.extendModules {
modules = [{programs.opencode-profile.mcpNixos.enable = false;}];
};

enabledFiles = enabled.config.xdg.configFile;
defaultsFiles = defaults.config.xdg.configFile;

Expand Down Expand Up @@ -102,6 +106,8 @@ in {
jq -e '.permission.edit."flake.lock" == "ask"' ${settingsJson}
jq -e '.permission.bash."rm -rf /*" == "deny"' ${settingsJson}
jq -e '.mcp.nix.type == "local"' ${settingsJson}
jq -e '.mcp.nix.enabled == true and (.mcp.nix.command | length) == 1' ${settingsJson}
test -x "$(jq -r '.mcp.nix.command[0]' ${settingsJson})"
jq -e '.theme == "tokyonight"' ${tuiJson}
grep -q "profile-check-marker" ${agentsMd}
grep -q "caveman" ${agentsMd}
Expand All @@ -121,6 +127,17 @@ in {
assert lib.assertMsg
(lib.count (p: lib.hasPrefix "opencode" (lib.getName p)) defaults.config.home.packages == 1)
"expected exactly one opencode package in home.packages";
assert lib.assertMsg
(let
command = defaults.config.programs.opencode.settings.mcp.nix.command;
in
builtins.length command
== 1
&& lib.hasPrefix "${builtins.storeDir}/" (builtins.head command)
&& lib.hasSuffix "/bin/mcp-nixos" (builtins.head command))
"nix MCP must launch a built executable without runtime flake resolution";
assert lib.assertMsg (!((withoutMcp.config.programs.opencode.settings.mcp or {}) ? nix))
"nix MCP registered despite mcpNixos.enable = false";
pkgs.runCommand "opencode-defaults-posture" {} "touch $out";

updater-mutation-only = pkgs.runCommand "opencode-updater-mutation-only" {} ''
Expand Down
57 changes: 57 additions & 0 deletions docs/nix-mcp-startup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Nix MCP startup fix

## Human seed and scope

> cant we keep both v1 and v2 working on durable option?
>
> do fix, but just merge to main now. No need to deploy yes

The verified source fix preserves the shared V1-compatible configuration
that V2 normalizes. mcp-nixos 2.4.3 is now a locked flake input, and the
Home Manager module launches its built executable directly. Deployment
realizes the closure; server startup no longer resolves a flake with `nix run`.
Local merge only; no push, consumer update, or deployment.

## Evidence

The original command initialized in 65.601 seconds during an isolated probe
with Nix download/cache retries. OpenCode V2's default startup budget is
30 seconds. The subsequent tool catalog loaded in 0.005 seconds.

Baseline `nix flake check --offline --no-build --no-write-lock-file` passed.
RED: `just check` failed with the new regression assertion:
`nix MCP must launch a built executable without runtime flake resolution`.
Direct execution of the already-built 2.4.3 package initialized in 1.914
seconds and listed tools in 0.005 seconds without executing any tool.

GREEN: `just check-full` passed all checks, including rendered V1-schema
validation, executable existence, single store-path command, and disabled
MCP registration. Existing direct dependency pins are unchanged; Nix renamed
the root nixpkgs lock node to `nixpkgs_2` when adding upstream dependencies.

Isolated runtime checks connected V1 1.18.30 in 7.876 seconds and V2 2.0.21
in 4.676 seconds using the same legacy MCP entry. Only initialization and
catalog discovery ran; no MCP tools executed. Temporary processes were stopped.

The initial full-check attempt exceeded its 120-second budget while fetching
dependencies through an unreachable cache. A 600-second rerun passed. V2 probe
repairs addressed diagnostic setup, not source: a one-shot list saw pending
initialization; direct HTTP lacked authentication. The successful probe used
an isolated registered service and OpenCode's authenticated API client.

## Review, limits, and recovery

Independent review found no code blockers; its stale-progress-note finding
is corrected here. No extra timeout, wrapper, package implementation, or
configuration schema was introduced.

Deployment remains intentionally deferred. The active V2 configuration is an
independent copied snapshot and is unchanged; a future separately authorized
refresh must adopt the generated command. No live service was restarted.
Recovery is to revert the fix commit and redeploy through the owning consumer
only when separately authorized.

Feedback: "this machine does have git credentials". Confirmed: V2's isolated
`XDG_CONFIG_HOME` hid the host Git configuration, including its author identity.
Git delivery commands use the host XDG config path temporarily; no identity,
credential, or global Git configuration changes are needed.
94 changes: 93 additions & 1 deletion flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};

mcp-nixos.url = "github:utensils/mcp-nixos/v2.4.3";
};

outputs = inputs @ {
Expand Down Expand Up @@ -85,7 +87,7 @@

flake = {
homeManagerModules = {
default = import ./modules/home-manager.nix;
default = import ./modules/home-manager.nix {mcpNixos = inputs.mcp-nixos;};
withPackage = {pkgs, ...}: {
imports = [self.homeManagerModules.default];
programs.opencode.package = self.packages.${pkgs.stdenv.hostPlatform.system}.opencode;
Expand Down
8 changes: 4 additions & 4 deletions modules/home-manager.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
{mcpNixos}: {
config,
lib,
pkgs,
...
}: let
cfg = config.programs.opencode-profile;
Expand Down Expand Up @@ -205,11 +206,10 @@ in {
permission = permissionDefaults;
})
// (lib.optionalAttrs cfg.mcpNixos.enable {
# Pinned tag, not a floating branch: `nix run` re-resolves at MCP
# server start, so an unpinned ref would drift per session.
# Realize the pinned package at deployment, not during MCP startup.
mcp.nix = {
type = "local";
command = ["nix" "run" "github:utensils/mcp-nixos/v2.4.3"];
command = [(lib.getExe mcpNixos.packages.${pkgs.stdenv.hostPlatform.system}.mcp-nixos)];
enabled = true;
};
});
Expand Down
Loading