feat(mcp): agenthub mcp install writes .mcp.json (auto-register)
One command, no hand-editing: `agenthub mcp install` writes/merges a project .mcp.json (the standard config Claude Code and other .mcp.json-aware clients auto-discover) with the hub URL filled in — so those agents register automatically. Prints the global-config snippet for Codex/Kimi as fallback. `--print` is a dry run. Bump 0.7.3 -> 0.7.4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
eec2050a32
commit
b004e9fbb4
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agenthub",
|
"name": "agenthub",
|
||||||
"version": "0.7.3",
|
"version": "0.7.4",
|
||||||
"description": "Local coordination layer for AI coding agents",
|
"description": "Local coordination layer for AI coding agents",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { watchEvents } from './commands/watch.js';
|
|||||||
import { startAgent } from './commands/start.js';
|
import { startAgent } from './commands/start.js';
|
||||||
import { workAgent } from './commands/work.js';
|
import { workAgent } from './commands/work.js';
|
||||||
import { startMcpServer } from '../mcp/server.js';
|
import { startMcpServer } from '../mcp/server.js';
|
||||||
import { printMcpConfig } from '../mcp/install.js';
|
import { installMcp } from '../mcp/install.js';
|
||||||
import { loadConfig, saveConfig } from '../core/config.js';
|
import { loadConfig, saveConfig } from '../core/config.js';
|
||||||
import { findProjectRoot } from '../core/paths.js';
|
import { findProjectRoot } from '../core/paths.js';
|
||||||
import { discoverServer } from '../discovery.js';
|
import { discoverServer } from '../discovery.js';
|
||||||
@ -116,7 +116,7 @@ async function runRemote(serverUrl: string, fn: () => Promise<void>): Promise<vo
|
|||||||
export function createProgram(cwd: string): Command {
|
export function createProgram(cwd: string): Command {
|
||||||
const program = new Command('agenthub')
|
const program = new Command('agenthub')
|
||||||
.description('Local coordination layer for AI coding agents')
|
.description('Local coordination layer for AI coding agents')
|
||||||
.version('0.7.3')
|
.version('0.7.4')
|
||||||
.option('--server <url>', 'AgentHub server URL (env: AGENTHUB_SERVER)');
|
.option('--server <url>', 'AgentHub server URL (env: AGENTHUB_SERVER)');
|
||||||
|
|
||||||
program
|
program
|
||||||
@ -486,10 +486,11 @@ export function createProgram(cwd: string): Command {
|
|||||||
// ─── mcp ───────────────────────────────────────────────────────────────────
|
// ─── mcp ───────────────────────────────────────────────────────────────────
|
||||||
program
|
program
|
||||||
.command('mcp [action]')
|
.command('mcp [action]')
|
||||||
.description('Start the MCP server (stdio). `agenthub mcp install` prints per-CLI registration config.')
|
.description('Start the MCP server (stdio). `agenthub mcp install` writes .mcp.json so MCP-aware agents auto-register.')
|
||||||
.action(async (action?: string) => {
|
.option('--print', 'Dry run: print the config instead of writing .mcp.json')
|
||||||
|
.action(async (action: string | undefined, options: { print?: boolean }) => {
|
||||||
if (action === 'install') {
|
if (action === 'install') {
|
||||||
printMcpConfig(cwd);
|
installMcp(cwd, { print: options.print });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await startMcpServer(cwd);
|
await startMcpServer(cwd);
|
||||||
|
|||||||
@ -1,13 +1,17 @@
|
|||||||
|
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
import { findProjectRoot } from '../core/paths.js';
|
import { findProjectRoot } from '../core/paths.js';
|
||||||
import { loadConfig } from '../core/config.js';
|
import { loadConfig } from '../core/config.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print ready-to-paste MCP registration config for each agent CLI, with the
|
* Register the AgentHub MCP server with as little friction as possible.
|
||||||
* hub URL filled in. The MCP server itself is `agenthub mcp` (stdio) — every
|
*
|
||||||
* client just needs to know to spawn it + which hub to talk to.
|
* Default: writes/merges a project `.mcp.json` — the standard config that Claude
|
||||||
|
* Code (and any `.mcp.json`-aware MCP client) auto-discovers, so those agents
|
||||||
|
* register with zero hand-editing. For CLIs that use a GLOBAL config instead
|
||||||
|
* (Codex / Kimi) it prints a ready-to-paste snippet. `--print` is a dry run.
|
||||||
*/
|
*/
|
||||||
export function printMcpConfig(cwd: string): void {
|
function resolveUrl(root: string): string {
|
||||||
const root = findProjectRoot(cwd) ?? cwd;
|
|
||||||
let serverUrl = process.env.AGENTHUB_SERVER || undefined;
|
let serverUrl = process.env.AGENTHUB_SERVER || undefined;
|
||||||
if (!serverUrl) {
|
if (!serverUrl) {
|
||||||
try {
|
try {
|
||||||
@ -16,44 +20,54 @@ export function printMcpConfig(cwd: string): void {
|
|||||||
/* no project config */
|
/* no project config */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const url = serverUrl ?? 'http://127.0.0.1:3377';
|
return serverUrl ?? 'http://127.0.0.1:3377';
|
||||||
|
}
|
||||||
|
|
||||||
const out = (s: string) => process.stdout.write(s + '\n');
|
export function installMcp(cwd: string, opts: { print?: boolean } = {}): void {
|
||||||
|
const root = findProjectRoot(cwd) ?? cwd;
|
||||||
|
const url = resolveUrl(root);
|
||||||
|
const serverDef = { command: 'agenthub', args: ['mcp'], env: { AGENTHUB_SERVER: url } };
|
||||||
|
const out = (s = '') => process.stdout.write(s + '\n');
|
||||||
|
|
||||||
out('');
|
out();
|
||||||
out('AgentHub MCP — registration');
|
out('AgentHub MCP — registration');
|
||||||
out('═══════════════════════════');
|
out('═══════════════════════════');
|
||||||
out(`Hub URL: ${url}`);
|
out(`Hub URL: ${url}`);
|
||||||
out('(On the Windows machine use the Mac\'s LAN IP, e.g. http://192.168.178.30:3377)');
|
|
||||||
out('');
|
|
||||||
out('The MCP server is `agenthub mcp` (stdio). Register it once per agent CLI:');
|
|
||||||
out('');
|
|
||||||
|
|
||||||
out('── Claude Code ──────────────────────────────────────────────');
|
const mcpJsonPath = join(root, '.mcp.json');
|
||||||
out(` claude mcp add agenthub --env AGENTHUB_SERVER=${url} -- agenthub mcp`);
|
if (opts.print) {
|
||||||
out(' (or add the .mcp.json block below to the project)');
|
|
||||||
out('');
|
out('');
|
||||||
|
out(`Would write ${mcpJsonPath}:`);
|
||||||
out('── .mcp.json (project root — Claude Code / generic) ─────────');
|
out(JSON.stringify({ mcpServers: { agenthub: serverDef } }, null, 2));
|
||||||
out(JSON.stringify(
|
} else {
|
||||||
{ mcpServers: { agenthub: { command: 'agenthub', args: ['mcp'], env: { AGENTHUB_SERVER: url } } } },
|
let json: { mcpServers?: Record<string, unknown> } = { mcpServers: {} };
|
||||||
null,
|
if (existsSync(mcpJsonPath)) {
|
||||||
2,
|
try {
|
||||||
));
|
json = JSON.parse(readFileSync(mcpJsonPath, 'utf-8')) as typeof json;
|
||||||
|
} catch {
|
||||||
|
json = { mcpServers: {} };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!json.mcpServers) json.mcpServers = {};
|
||||||
|
json.mcpServers.agenthub = serverDef;
|
||||||
|
writeFileSync(mcpJsonPath, JSON.stringify(json, null, 2) + '\n', 'utf-8');
|
||||||
out('');
|
out('');
|
||||||
|
out(`✓ Wrote ${mcpJsonPath}`);
|
||||||
|
out(' → Claude Code (and any .mcp.json-aware client) opened here auto-registers it.');
|
||||||
|
}
|
||||||
|
|
||||||
out('── Codex CLI (~/.codex/config.toml) ─────────────────────────');
|
out('');
|
||||||
|
out('For CLIs that use a GLOBAL config instead of project .mcp.json:');
|
||||||
|
out('');
|
||||||
|
out('── Codex (~/.codex/config.toml) ──');
|
||||||
out(' [mcp_servers.agenthub]');
|
out(' [mcp_servers.agenthub]');
|
||||||
out(' command = "agenthub"');
|
out(' command = "agenthub"');
|
||||||
out(' args = ["mcp"]');
|
out(' args = ["mcp"]');
|
||||||
out(` env = { AGENTHUB_SERVER = "${url}" }`);
|
out(` env = { AGENTHUB_SERVER = "${url}" }`);
|
||||||
out('');
|
out('');
|
||||||
|
out('── Kimi (its MCP config) ──');
|
||||||
out('── Kimi CLI ─────────────────────────────────────────────────');
|
out(` stdio server — command: agenthub args: ["mcp"] env: AGENTHUB_SERVER=${url}`);
|
||||||
out(' Add a stdio MCP server via Kimi\'s MCP config with the same shape:');
|
|
||||||
out(' command: agenthub args: ["mcp"] env: { AGENTHUB_SERVER: ' + url + ' }');
|
|
||||||
out('');
|
out('');
|
||||||
out('After registering, the agent calls the tools (agenthub_work, agenthub_task_review, …)');
|
out('On Windows use the Mac LAN IP (e.g. http://192.168.178.30:3377). Requires agenthub >= 0.7.0.');
|
||||||
out('instead of CLI strings. Requires agenthub >= 0.7.0 on each machine.');
|
|
||||||
out('');
|
out('');
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user