From c0e73bc3f277fcfe507be6d6cd7d29fd9442a2e7 Mon Sep 17 00:00:00 2001 From: joaovictor91123 Date: Sun, 12 Jul 2026 21:41:07 +0400 Subject: [PATCH] docs(miner): add MCP client config example combining gittensory-mcp and gittensory-miner-mcp Adds a copy-pasteable mcpServers JSON snippet to the miner README's MCP server section showing how a dual-role operator running both ORB and AMS can register both stdio servers in one client config, plus a doc-lint test asserting the snippet stays valid JSON with the correct server shapes. Closes #5163 --- packages/gittensory-miner/README.md | 21 +++++++++ test/unit/miner-mcp-client-config-doc.test.ts | 47 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 test/unit/miner-mcp-client-config-doc.test.ts diff --git a/packages/gittensory-miner/README.md b/packages/gittensory-miner/README.md index 06920f65b4..e1167ff549 100644 --- a/packages/gittensory-miner/README.md +++ b/packages/gittensory-miner/README.md @@ -151,6 +151,27 @@ It exposes these read-only tools: Further AMS-state-reading tools (status/doctor diagnostics) land as follow-up PRs on top of this server. +### Client config + +`gittensory-mcp` (ORB's hosted contributor-workflow tools) and `gittensory-miner-mcp` (AMS's own local state-visibility tools above) can run as two separate stdio servers in the same MCP client session — useful for a dual-role operator running both ORB and AMS on the same box. Generate ORB's half with `gittensory-mcp init-client --print claude` (see the [`@jsonbored/gittensory-mcp` README](../gittensory-mcp/README.md#client-config)); `gittensory-miner-mcp` takes no flags, so its entry is just the bin name. Combined, a Claude Desktop / Claude Code style config looks like: + +```json +{ + "mcpServers": { + "gittensory": { + "command": "gittensory-mcp", + "args": ["--stdio"] + }, + "gittensory-miner": { + "command": "gittensory-miner-mcp", + "args": [] + } + } +} +``` + +`gittensory` exposes ORB's hosted contributor-workflow tools (issue ranking, PR packet prep, decision packs). `gittensory-miner` exposes AMS's own local state-visibility tools listed above (portfolio dashboard, claims, audit feed, run state, plans) — a fully separate, 100% local tool surface with no shared code or network calls between the two. + ## Version check On every invocation the CLI starts an async npm registry lookup (5s timeout). When the installed package is behind `@jsonbored/gittensory-miner@latest`, it prints a one-line upgrade command to stderr without blocking or failing the requested command. Set `GITTENSORY_NPM_REGISTRY_URL` to point at a mirror, same as `@jsonbored/gittensory-mcp`. diff --git a/test/unit/miner-mcp-client-config-doc.test.ts b/test/unit/miner-mcp-client-config-doc.test.ts new file mode 100644 index 0000000000..29fb6d1297 --- /dev/null +++ b/test/unit/miner-mcp-client-config-doc.test.ts @@ -0,0 +1,47 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, it } from "vitest"; + +const README_PATH = join(process.cwd(), "packages/gittensory-miner/README.md"); +const MCP_README_PATH = join(process.cwd(), "packages/gittensory-mcp/README.md"); + +/** Pulls the first ```json fenced block out of a markdown doc. Throws if none is found, so a doc edit that + * accidentally drops the fence (rather than its content) fails loudly instead of silently skipping. */ +function extractFirstJsonBlock(markdown: string): string { + const match = markdown.match(/```json\r?\n([\s\S]*?)\r?\n```/); + if (!match || match[1] === undefined) throw new Error("No ```json fenced block found in the given markdown."); + return match[1]; +} + +describe("miner MCP client config example (#5163)", () => { + it("documents running gittensory-mcp and gittensory-miner-mcp together", () => { + const readme = readFileSync(README_PATH, "utf8"); + expect(readme).toContain("### Client config"); + expect(readme).toContain("gittensory-mcp init-client --print claude"); + // Explains what each server is for, not just how to wire it up. + expect(readme).toContain("contributor-workflow tools"); + expect(readme).toContain("state-visibility tools"); + }); + + it("ships a copy-pasteable, valid mcpServers JSON snippet registering both servers", () => { + const readme = readFileSync(README_PATH, "utf8"); + const config = JSON.parse(extractFirstJsonBlock(readme)); + + expect(config.mcpServers.gittensory).toEqual({ + command: "gittensory-mcp", + args: ["--stdio"], + }); + expect(config.mcpServers["gittensory-miner"]).toEqual({ + command: "gittensory-miner-mcp", + args: [], + }); + }); + + it("cross-references the ORB MCP README's own Client config section", () => { + const readme = readFileSync(README_PATH, "utf8"); + expect(readme).toContain("../gittensory-mcp/README.md#client-config"); + + const mcpReadme = readFileSync(MCP_README_PATH, "utf8"); + expect(mcpReadme).toContain("### Client config"); + }); +});