claude-code: add enableMcpIntegration
Some checks failed
/ triage (push) Has been cancelled
GitHub Pages / publish (ubuntu-latest) (push) Has been cancelled

Add `enableMcpIntegration` option to merge MCP servers from
`programs.mcp.servers` into Claude Code configuration. Claude Code
servers take precedence over general MCP servers when both define
the same server name.
This commit is contained in:
Thierry Delafontaine 2026-01-18 04:33:01 +01:00 committed by GitHub
parent 1c27557d99
commit 83bcb17377
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 106 additions and 5 deletions

View file

@ -7,6 +7,17 @@
let
cfg = config.programs.claude-code;
jsonFormat = pkgs.formats.json { };
transformedMcpServers = lib.optionalAttrs (cfg.enableMcpIntegration && config.programs.mcp.enable) (
lib.mapAttrs (
name: server:
(removeAttrs server [ "disabled" ])
// (lib.optionalAttrs (server ? url) { type = "http"; })
// (lib.optionalAttrs (server ? command) { type = "stdio"; })
// {
enabled = !(server.disabled or false);
}
) config.programs.mcp.servers
);
in
{
meta.maintainers = [ lib.maintainers.khaneliman ];
@ -23,6 +34,20 @@ in
description = "Resulting customized claude-code package.";
};
enableMcpIntegration = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to integrate the MCP servers config from
{option}`programs.mcp.servers` into
{option}`programs.opencode.settings.mcp`.
Note: Settings defined in {option}`programs.mcp.servers` are merged
with {option}`programs.claude-code.mcpServers`, with Claude Code servers
taking precedence.
'';
};
settings = lib.mkOption {
inherit (jsonFormat) type;
default = { };
@ -359,8 +384,8 @@ in
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.mcpServers == { } || cfg.package != null;
message = "`programs.claude-code.package` cannot be null when `mcpServers` is configured";
assertion = (cfg.mcpServers == { } && !cfg.enableMcpIntegration) || cfg.package != null;
message = "`programs.claude-code.package` cannot be null when `mcpServers` or `enableMcpIntegration` is configured";
}
{
assertion = !(cfg.memory.text != null && cfg.memory.source != null);
@ -390,11 +415,14 @@ in
programs.claude-code.finalPackage =
let
mergedMcpServers = transformedMcpServers // cfg.mcpServers;
makeWrapperArgs = lib.flatten (
lib.filter (x: x != [ ]) [
(lib.optional (cfg.mcpServers != { }) [
(lib.optional (cfg.mcpServers != { } || transformedMcpServers != { }) [
"--append-flags"
"--mcp-config ${jsonFormat.generate "claude-code-mcp-config.json" { inherit (cfg) mcpServers; }}"
"--mcp-config ${
jsonFormat.generate "claude-code-mcp-config.json" { mcpServers = mergedMcpServers; }
}"
])
]
);

View file

@ -47,7 +47,7 @@
};
test.asserts.assertions.expected = [
"`programs.claude-code.package` cannot be null when `mcpServers` is configured"
"`programs.claude-code.package` cannot be null when `mcpServers` or `enableMcpIntegration` is configured"
"Cannot specify both `programs.claude-code.memory.text` and `programs.claude-code.memory.source`"
"Cannot specify both `programs.claude-code.agents` and `programs.claude-code.agentsDir`"
"Cannot specify both `programs.claude-code.commands` and `programs.claude-code.commandsDir`"

View file

@ -2,6 +2,7 @@
claude-code-basic = ./basic.nix;
claude-code-full-config = ./full-config.nix;
claude-code-mcp = ./mcp.nix;
claude-code-mcp-integration = ./mcp-integration.nix;
claude-code-assertion = ./assertion.nix;
claude-code-memory-management = ./memory-management.nix;
claude-code-memory-from-source = ./memory-from-source.nix;

View file

@ -0,0 +1,72 @@
{ config, ... }:
{
programs = {
claude-code = {
package = config.lib.test.mkStubPackage {
name = "claude-code";
buildScript = ''
mkdir -p $out/bin
touch $out/bin/claude
chmod 755 $out/bin/claude
'';
};
enable = true;
enableMcpIntagretion = true;
mcpServers = {
github = {
type = "http";
url = "https://api.githubcopilot.com/mcp/";
};
filesystem = {
type = "stdio";
command = "npx";
args = [
"-y"
"@modelcontextprotocol/server-filesystem"
"/tmp"
];
};
};
};
mcp = {
enable = true;
servers = {
filesystem = {
type = "stdio";
command = "npx";
args = [
"-y"
"@modelcontextprotocol/server-filesystem"
"/other-tmp"
];
};
database = {
command = "npx";
args = [
"-y"
"@bytebase/dbhub"
"--dsn"
"postgresql://user:pass@localhost:5432/db"
];
env = {
DATABASE_URL = "postgresql://user:pass@localhost:5432/db";
};
};
customTransport = {
type = "websocket";
url = "wss://example.com/mcp";
customOption = "value";
timeout = 5000;
};
};
};
};
nmt.script = ''
normalizedWrapper=$(normalizeStorePaths home-path/bin/claude)
assertFileContent $normalizedWrapper ${./expected-mcp-wrapper}
'';
}