From 2e87c0e2fc206171c64f9e9e6128dceb362667d1 Mon Sep 17 00:00:00 2001 From: Martin Bens Date: Fri, 2 Oct 2026 18:14:22 +0200 Subject: [PATCH 01/14] chore: add software-writer extensions for Claude Code and Codex The writing-code, writing-tests, and writing-docs skills ran on their generic defaults in this repository, without the wrapper helpers, test runners, or documentation surface map they need to apply their rules here. The three files under .claude/extensions/software-writer/ register the helpers in mcp-server-gh/lib/common.sh, hooks/scripts/lib/common.sh, and pi/gate.ts that new code must call instead of raw gh, jq, or child_process calls; the BATS and node:test runners with their shared fixtures and the rule that tests stay correct under bats --jobs; the ShellCheck, tsc, and ESLint gates CI runs; and the owner of each fact across the README, AGENTS.md, REFERENCE.md, SETUP.md, and CHANGELOG surfaces. Claude Code loads the files through the software-writer plugin. Codex reads them through the new root AGENTS.override.md, which first sends it to AGENTS.md because the override replaces that file rather than adding to it. .gitignore now excepts .claude/extensions/ from the .claude/* rule so the files are tracked. Co-Authored-By: Claude --- .../software-writer/writing-code.md | 51 +++++++++++++++++++ .../software-writer/writing-docs.md | 25 +++++++++ .../software-writer/writing-tests.md | 24 +++++++++ .gitignore | 1 + AGENTS.override.md | 30 +++++++++++ 5 files changed, 131 insertions(+) create mode 100644 .claude/extensions/software-writer/writing-code.md create mode 100644 .claude/extensions/software-writer/writing-docs.md create mode 100644 .claude/extensions/software-writer/writing-tests.md create mode 100644 AGENTS.override.md diff --git a/.claude/extensions/software-writer/writing-code.md b/.claude/extensions/software-writer/writing-code.md new file mode 100644 index 0000000..df59a7a --- /dev/null +++ b/.claude/extensions/software-writer/writing-code.md @@ -0,0 +1,51 @@ +## Named-value assignments + +- `project.stacks` = + - `bash` — `plugins/**/*.sh`, `.github/scripts/*.sh`, `plugin-tests/**/*.{bats,bash,sh}` + - `typescript` — `plugins/github-mcp/pi/*.ts`, `plugin-tests/github-mcp/{pi,fixtures/pi}/*.ts`; executed directly by Node ≥22.19 type stripping, no build step (`tsconfig.json`: `erasableSyntaxOnly`, `allowImportingTsExtensions`; relative imports keep the `.ts` extension) +- `code.primitives` = + | Call shape | Raw primitive | Helper | Invariant carried | + |---|---|---|---| + | Resolve the target repository from tool args | `jq` reads of `repo` / `repository` / `owner` / `url` | `_gh_resolve_owner_repo`, `_gh_resolve_owner_repo_optional` (`mcp-server-gh/lib/common.sh`) | Precedence `url` > `owner`+`repo` > `repository` > `repo` > `GH_DEFAULT_REPO`; a slash in split-form `repo` is rejected | + | Resolve an organization | `gh repo view`, raw `org` arg | `_gh_resolve_org` (`lib/common.sh`) | Result always passes `_gh_validate_org`, so it cannot steer the request to another API path | + | Validate a number, repo, SHA, or repository path argument | Ad hoc `[[ =~ ]]` checks | `_gh_validate_number`, `_gh_validate_repo`, `_gh_validate_sha`, `_gh_validate_path` (`lib/common.sh`) | `_gh_validate_path` rejects a leading `/` and any `..` segment | + | Apply caller-supplied `jq_filter` / `grep_pattern` / `head` / `tail` | Piping output through `jq` or `grep` directly | `_gh_validate_jq_filter`, `_gh_post_process` (`lib/common.sh`) | Filter compile-checked before use; steps run in a fixed jq → grep → head → tail order, each a no-op when unset | + | Emit `gh` output to the model | Raw `gh` stdout | `_gh_strip_ansi` (`lib/common.sh`) | No ESC byte reaches a terminal-rendering host; BSD-`sed`-compatible BRE under `LC_ALL=C` | + | Download file bytes to disk | `gh api … > file`, `mktemp` | `_gh_download_file` with `_gh_partial_create` / `_gh_partial_finish` / `_gh_partial_cleanup` (`lib/common.sh`) | Unique `noclobber` naming, atomic finish, partial file removed on cancellation | + | Locate the project config file | Hand-listed `.claude` / `.codex` / `.pi` candidate paths | `_load_gh_config` (`mcp-server-gh/lib/common.sh`, servers), `find_mcp_config` (`hooks/scripts/lib/common.sh`, hooks), both ordered by `github_mcp_config_dirs` (`shared/config-dirs.sh`) | The active host's directory takes priority, and servers and hooks agree on one host order | + | Read a config key | `jq` on `$GH_TOOLING_CONFIG_FILE` | `_gh_config_value` (`lib/common.sh`) | Returns the default when the file is missing or the key empty | + | Run a hook script from the pi extension | `child_process.spawn` | `runScript`, `runGate` (`plugins/github-mcp/pi/gate.ts`) | Never rejects; timeout kills the whole process group; sets `GITHUB_MCP_HOST=pi` and drops `CLAUDE_PROJECT_DIR`; blocks only on exit 2 | + | Invoke `gh` | A command string | `local -a cmd=(gh …)` then `"${cmd[@]}"` | Arguments stay array elements; never `eval` | +- `code.di_pattern` = TypeScript: the default export `githubMcp(pi: ExtensionAPI)` in `plugins/github-mcp/pi/index.ts` is the composition root; it computes script paths and timeouts and wires `pi.on(...)` handlers. Modules beside it (`gate.ts`) take script path, input, and timeout as parameters and hold no module-level state. Bash: a tool function `tool_()` takes the JSON args string as `$1`; host and project context enter through environment variables set at the server or hook entry point (`GITHUB_MCP_HOST`, `CLAUDE_PROJECT_DIR`, `MCP_GH_TOOLING_CONFIG`, `GH_DEFAULT_REPO`, `PROJECT_ROOT`); `gh` resolves from PATH, so tests substitute a `gh()` function. +- `code.export_conventions` = + - `plugins/github-mcp/pi/index.ts` exports only the default extension factory named in root `package.json` `pi.extensions`; helpers live in sibling modules as named exports. + - Import `@earendil-works/*` packages only with `import type`; the extension carries no runtime dependency on pi (`@typescript-eslint/no-restricted-imports` in `eslint.config.mjs` enforces this for `plugins/github-mcp/pi/**/*.ts`). + - A new MCP tool is a `tool_()` in `mcp-server-gh/lib/.sh` plus its schema entry in `tools-read.json` or `tools-write.json`; a server runs only the tools its list declares. Before adding one, read `plugins/github-mcp/AGENTS.md` §When to Modify What. +- `code.footgun_additions` = + - `plugins/github-mcp/shared/mcpserver_core.sh` is vendored from `shopwareLabs/bash-mcp-sdk`: never edit it; protocol changes go upstream and arrive via `.mcp-sdk.lock` plus `.github/scripts/vendor-mcp-sdk.sh`. + - pi extension `.ts` files run under Node type stripping: no `enum`, `namespace`, parameter properties, or other non-erasable syntax. + - A new runtime file outside the root `package.json` `files` globs is missing from the npm package; only `plugin-tests/github-mcp/pi_e2e.bats`, which runs pi against the packed tarball, surfaces it. + - Host-specific behavior branches only on `GITHUB_MCP_HOST` (servers) or `HOOK_HOST` (hooks); runtime scripts stay shared across Claude Code, Codex, and pi. + - Adding or removing a plugin, MCP server, or hook requires running `.github/scripts/update-issue-templates.sh`; CI fails on stale issue-template dropdowns. +- `comments.preserve_patterns` = + - `# shellcheck disable=…` and `# shellcheck source=…` directives, together with the justification comment beside them + - The `# Tools: ` header line in `plugins/github-mcp/mcp-server-gh/lib/*.sh` +- `domain.terms` = `read server`, `write server`, `gh-tooling`, `gh-tooling-write` (server IDs; distinct from the plugin name `github-mcp`), `host`, `SessionStart directive`, `enforcement`, `escape hatch`, `enforce_mcp_tools`, `enable_write_server`, `block_api_commands`, `block_api_tool_read`, `block_api_tool_write` +- `docs.surfaces` = + | Surface | Owns | Shape | Single-owner | + |---|---|---|---| + | `README.md` | Marketplace pitch, per-host install commands, component summary, pointers into plugin docs | Root README | enforced | + | `AGENTS.md` | Three-host model, runtime-vs-docs file split, repository architecture, development workflow, version bumps, test commands, pre-release checklist, release and distribution | Architecture document | enforced | + | `CLAUDE.md`, `plugins/plugin-setup/CLAUDE.md` | Nothing; a one-line `@AGENTS.md` import. Gitignored and local to each checkout: never the home for a shared fact | LLM pointer file | not applicable | + | `plugins/github-mcp/README.md` | Configuration keys and lookup order, tool catalog and tool counts, write server, label semantics, enforcement layers, blocked commands, pi notes, troubleshooting, dependencies | Module README | enforced, except §Quick Start: exempt duplicate of the root README install commands because this file is the npm package homepage and must stand alone | + | `plugins/github-mcp/AGENTS.md` | Plugin file layout, config-loading internals, protocol flow, tool dispatch convention, standard execution block, task-to-file navigation, suite-to-coverage table | Module architecture and navigation document | enforced | + | `plugins/github-mcp/REFERENCE.md` | Per-tool parameters and examples | Reference | enforced | + | `plugins/github-mcp/SETUP.md` | Interactive setup procedure, permission groups | Guide | exempt: kept byte-identical to `plugins/plugin-setup/skills/github-mcp-setting-up/references/plugin-setup.md` | + | `plugins/plugin-setup/README.md`, `plugins/plugin-setup/AGENTS.md` | Setup-plugin install and usage; skill layout, setup-copy sync procedure, design decisions | Module README; module navigation document | enforced | + | `plugins/github-mcp/CHANGELOG.md`, `plugins/plugin-setup/CHANGELOG.md` | Released changes per version | Changelog | exempt: each entry restates what its release changed | + + Runtime prompt text under `plugins/github-mcp/hooks/prompts/*.md` and `plugins/plugin-setup/skills/*/SKILL.md` are runtime files, not documentation surfaces. + +## Post-Step-6 + +After editing a `.sh` file, run `shellcheck --shell=bash` on it; CI lints all of `plugins/`, `plugin-tests/`, and `.github/scripts/`. After editing a `.ts` file, run `npx tsc --noEmit -p .` and `npx eslint . --max-warnings 0`. diff --git a/.claude/extensions/software-writer/writing-docs.md b/.claude/extensions/software-writer/writing-docs.md new file mode 100644 index 0000000..1d3c091 --- /dev/null +++ b/.claude/extensions/software-writer/writing-docs.md @@ -0,0 +1,25 @@ +## Named-value assignments + +- `docs.surfaces` = + | Surface | Owns | Shape | Single-owner | + |---|---|---|---| + | `README.md` | Marketplace pitch, per-host install commands, component summary, pointers into plugin docs | Root README | enforced | + | `AGENTS.md` | Three-host model, runtime-vs-docs file split, repository architecture, development workflow, version bumps, test commands, pre-release checklist, release and distribution | Architecture document | enforced | + | `CLAUDE.md`, `plugins/plugin-setup/CLAUDE.md` | Nothing; a one-line `@AGENTS.md` import. Gitignored and local to each checkout: never the home for a shared fact | LLM pointer file | not applicable | + | `plugins/github-mcp/README.md` | Configuration keys and lookup order, tool catalog and tool counts, write server, label semantics, enforcement layers, blocked commands, pi notes, troubleshooting, dependencies | Module README | enforced, except §Quick Start: exempt duplicate of the root README install commands because this file is the npm package homepage and must stand alone | + | `plugins/github-mcp/AGENTS.md` | Plugin file layout, config-loading internals, protocol flow, tool dispatch convention, standard execution block, task-to-file navigation, suite-to-coverage table | Module architecture and navigation document | enforced | + | `plugins/github-mcp/REFERENCE.md` | Per-tool parameters and examples | Reference | enforced | + | `plugins/github-mcp/SETUP.md` | Interactive setup procedure, permission groups | Guide | exempt: kept byte-identical to `plugins/plugin-setup/skills/github-mcp-setting-up/references/plugin-setup.md` | + | `plugins/plugin-setup/README.md`, `plugins/plugin-setup/AGENTS.md` | Setup-plugin install and usage; skill layout, setup-copy sync procedure, design decisions | Module README; module navigation document | enforced | + | `plugins/github-mcp/CHANGELOG.md`, `plugins/plugin-setup/CHANGELOG.md` | Released changes per version | Changelog | exempt: each entry restates what its release changed | + + Runtime prompt text under `plugins/github-mcp/hooks/prompts/*.md` and `plugins/plugin-setup/skills/*/SKILL.md` are runtime files, not documentation surfaces. +- `docs.pointer_file` = `CLAUDE.md` — a gitignored, per-checkout single `@AGENTS.md` line; each `AGENTS.md` in turn opens with `@README.md` +- `docs.jargon_home` = `AGENTS.md` +- `docs.changelog` = `plugins/github-mcp/CHANGELOG.md` and `plugins/plugin-setup/CHANGELOG.md`; Keep a Changelog with `## [x.y.z] - YYYY-MM-DD` entries, each version matching its plugin manifest version + +## Post-Step-5 + +After editing `plugins/github-mcp/SETUP.md`, follow the sync procedure in `plugins/plugin-setup/AGENTS.md` §The skill, then confirm the copy with `cmp plugins/github-mcp/SETUP.md plugins/plugin-setup/skills/github-mcp-setting-up/references/plugin-setup.md`. + +When the change documents altered tool behavior, confirm both `plugins/github-mcp/README.md` and `plugins/github-mcp/REFERENCE.md` were updated. diff --git a/.claude/extensions/software-writer/writing-tests.md b/.claude/extensions/software-writer/writing-tests.md new file mode 100644 index 0000000..7282c96 --- /dev/null +++ b/.claude/extensions/software-writer/writing-tests.md @@ -0,0 +1,24 @@ +## Named-value assignments + +- `project.stacks` = + - `bash` — `plugins/**/*.sh`, `.github/scripts/*.sh`, `plugin-tests/**/*.{bats,bash,sh}` + - `typescript` — `plugins/github-mcp/pi/*.ts`, `plugin-tests/github-mcp/{pi,fixtures/pi}/*.ts`; executed directly by Node ≥22.19 type stripping, no build step (`tsconfig.json`: `erasableSyntaxOnly`, `allowImportingTsExtensions`; relative imports keep the `.ts` extension) +- `tests.frameworks` = + - BATS (bats-core + bats-support + bats-assert, vendored into `.bats/` by `.github/scripts/setup-bats.sh`) for every `plugin-tests/**/*.bats`. Run with `.bats/bats-core/bin/bats -r plugin-tests/`. No BATS framework reference ships with the skill: apply the universal rules. Every suite opens with `# bats file_tags=github-mcp,[,]` and `bats_require_minimum_version 1.11.0`; keep both on new suites. + - `node:test` for `plugin-tests/github-mcp/pi/*.test.ts`. Run with `node --test 'plugin-tests/github-mcp/pi/*.test.ts'`; type-checked by `npx tsc --noEmit -p .`. + - End-to-end layer: `plugin-tests/github-mcp/pi_e2e.bats` drives the real `node_modules/.bin/pi` with `--offline` against the scripted faux model in `plugin-tests/github-mcp/fixtures/pi/driver.ts`. Requires `npm ci` and GNU `timeout` or `gtimeout` on PATH. +- `tests.fixture_sources` = + - `plugin-tests/test_helper/common_setup.bash` — `run_hook`, `assert_hook_blocks`, `setup_config`, `setup_codex_config` for hook-script suites. + - `plugin-tests/github-mcp/test_helper/common_setup.bash` — path constants `PLUGIN_DIR`, `SCRIPTS_DIR`, `SESSION_SCRIPT`, `SHARED_DIR`, `GH_SERVER_DIR`, `GH_LIB_DIR`, and the default `setup()`; load it with `load 'test_helper/common_setup'` instead of hardcoding `plugins/github-mcp/` paths. + - Stubbing `gh` in tool-function suites: define a `gh()` function override in `setup()` driven by `GH_STUB_OUTPUT`, `GH_STUB_STDERR`, and `GH_STUB_EXIT`, reset in `setup()`. + - pi end-to-end only: `plugin-tests/github-mcp/fixtures/pi/gh-stub.sh` (PATH-shim `gh`, logs to `$GH_LOG`) and the `$SCENARIO`-selected scripts in `fixtures/pi/driver.ts`. + - `node:test`: per-test temp directories from `mkdtempSync(join(tmpdir(), …))` removed in `t.after`. +- `tests.parallelism` = Both runners currently execute serially: CI runs `bats --timing -r plugin-tests/` without `--jobs`, and no `plugin-tests/github-mcp/pi/*.test.ts` file sets `concurrency`. Write every test to stay correct under `bats --jobs`: per-test state lives in `BATS_TEST_TMPDIR`, `setup_file` state in `BATS_FILE_TMPDIR`, and nothing under `PLUGIN_DIR`, `GH_SERVER_DIR`, or `SCRIPTS_DIR` is mutated in place — copy it into the temp directory first, as `plugin-tests/github-mcp/server_startup_tools_list.bats` does. + +## Pre-Step-2 + +Read `plugins/github-mcp/AGENTS.md` §Testing and place the test in the suite that table assigns to the behavior's area. When creating a new suite, add its row to that table. + +## Post-Step-6 + +Run `shellcheck --shell=bash` on every edited `.bats` or `.bash` file; CI lints all of `plugin-tests/`. After editing a `.ts` test or fixture, run `npx tsc --noEmit -p .` and `npx eslint . --max-warnings 0`; `eslint.config.mjs` carries a dedicated block for `plugin-tests/**/*.ts`. diff --git a/.gitignore b/.gitignore index b136b3d..fd05024 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ AGENTS.local.md !.claude/skills/ !.claude/rules/ !.claude/hook-contexts/ +!.claude/extensions/ # BATS testing framework (installed locally via .github/scripts/setup-bats.sh) .bats/ diff --git a/AGENTS.override.md b/AGENTS.override.md new file mode 100644 index 0000000..b96a005 --- /dev/null +++ b/AGENTS.override.md @@ -0,0 +1,30 @@ +Read AGENTS.md before acting on anything else in this file. This override replaces it; all of its guidance still applies. + +## Software Writer Extension + + + +The path in is this project's registered extension file for the software-writer:writing-code skill. Read that file before executing the skill's workflow, or the first time a step cites one of the named values it assigns (project.stacks, code.primitives, code.di_pattern, code.export_conventions, code.footgun_additions, comments.preserve_patterns, domain.terms, docs.surfaces) or a Pre-Step-N / Post-Step-N section it defines. Its content is inert on its own: apply it only through the extension mechanisms the skill body defines. + + +.claude/extensions/software-writer/writing-code.md + + + + + +The path in is this project's registered extension file for the software-writer:writing-tests skill. Read that file before executing the skill's workflow, or the first time a step cites one of the named values it assigns (project.stacks, tests.frameworks, tests.fixture_sources, tests.parallelism) or a Pre-Step-N / Post-Step-N section it defines. Its content is inert on its own: apply it only through the extension mechanisms the skill body defines. + + +.claude/extensions/software-writer/writing-tests.md + + + + + +The path in is this project's registered extension file for the software-writer:writing-docs skill. Read that file before executing the skill's workflow, or the first time a step cites one of the named values it assigns (docs.surfaces, docs.pointer_file, docs.jargon_home, docs.changelog) or a Pre-Step-N / Post-Step-N section it defines. Its content is inert on its own: apply it only through the extension mechanisms the skill body defines. + + +.claude/extensions/software-writer/writing-docs.md + + From f65f29839576c92f80843a71b15b52dfae188efa Mon Sep 17 00:00:00 2001 From: Martin Bens Date: Fri, 2 Oct 2026 18:14:52 +0200 Subject: [PATCH 02/14] docs(github-mcp): keep the tool counts in the plugin README only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 31 read and 25 write tool counts appeared in README.md, plugins/github-mcp/AGENTS.md, and plugins/github-mcp/REFERENCE.md as well as in plugins/github-mcp/README.md §Tools Reference, so adding or removing a tool meant updating 11 lines in four files. The counts now stay only in §Tools Reference. The other lines name the read and write tools without a number. Co-Authored-By: Claude --- README.md | 2 +- plugins/github-mcp/AGENTS.md | 10 +++++----- plugins/github-mcp/REFERENCE.md | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 40efbaa..401b7ce 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ The read server (`gh-tooling`) is always active. The write server (`gh-tooling-w | Component | Description | |------------|------------------------------------------------------------------------------------------------------| -| 🔌 MCP | Two servers — `gh-tooling` (31 read tools) and `gh-tooling-write` (25 write tools, gated) | +| 🔌 MCP | Two servers: `gh-tooling` (read tools) and `gh-tooling-write` (write tools, gated) | | 🪝 Hooks | SessionStart directive + PreToolUse enforcement that redirects `gh` bash calls to the MCP tools | See [plugins/github-mcp/README.md](./plugins/github-mcp/README.md) for full configuration, the complete tool reference, and troubleshooting. See [plugins/github-mcp/REFERENCE.md](./plugins/github-mcp/REFERENCE.md) for per-tool parameter docs. diff --git a/plugins/github-mcp/AGENTS.md b/plugins/github-mcp/AGENTS.md index 98d103a..1da55d8 100644 --- a/plugins/github-mcp/AGENTS.md +++ b/plugins/github-mcp/AGENTS.md @@ -5,7 +5,7 @@ ``` plugins/github-mcp/ ├── README.md # User documentation (usage, configuration, troubleshooting) -├── REFERENCE.md # Full tool parameter docs and examples (31 read + 25 write tools) +├── REFERENCE.md # Full tool parameter docs and examples ├── AGENTS.md # LLM navigation guide (this file) ├── CHANGELOG.md # Version history ├── SETUP.md # Interactive setup procedure (kept byte-identical to plugin-setup's copy) @@ -42,8 +42,8 @@ plugins/github-mcp/ ├── server-write.sh # Write server entry point - gated by enable_write_server config ├── config-read.json # Read server metadata (name="gh-tooling") ├── config-write.json # Write server metadata (name="gh-tooling-write") - ├── tools-read.json # 31 read tools (PR, issue, CI, commit, search, repo, release, label, project, api_read) - ├── tools-write.json # 25 write tools (PR lifecycle, reviews, issues, issue types/fields, labels, assignees, sub-issues, projects, api) + ├── tools-read.json # Read tools (PR, issue, CI, commit, search, repo, release, label, project, api_read) + ├── tools-write.json # Write tools (PR lifecycle, reviews, issues, issue types/fields, labels, assignees, sub-issues, projects, api) ├── tools-empty.json # Tools list the write server reports while enable_write_server is false ├── mcp-gh-tooling.schema.json # JSON Schema for .mcp-gh-tooling.json └── lib/ @@ -73,8 +73,8 @@ plugins/github-mcp/ This plugin provides: - **Two MCP Servers** via `.mcp.json` in Claude Code and inline `mcpServers` in `.codex-plugin/plugin.json` in Codex: - - `gh-tooling` (read) - 31 read-only GitHub tools (PRs, issues, CI, commits, search, repo, releases, labels, projects, read-only API) - - `gh-tooling-write` (write) - 25 write tools (PR lifecycle, reviews, issues, issue types/fields, labels, assignees, sub-issues, projects, full API). Gated by `enable_write_server` config flag. + - `gh-tooling` (read) - read-only GitHub tools (PRs, issues, CI, commits, search, repo, releases, labels, projects, read-only API) + - `gh-tooling-write` (write) - write tools (PR lifecycle, reviews, issues, issue types/fields, labels, assignees, sub-issues, projects, full API). Gated by `enable_write_server` config flag. - **SessionStart Hook** via the shared `hooks/hooks.json`: - Assembles MCP tool directives dynamically from template with conditional write and label sections - Prompt template maintained in `hooks/prompts/mcp-tool-directives.md` diff --git a/plugins/github-mcp/REFERENCE.md b/plugins/github-mcp/REFERENCE.md index 60deaf1..b116479 100644 --- a/plugins/github-mcp/REFERENCE.md +++ b/plugins/github-mcp/REFERENCE.md @@ -2,7 +2,7 @@ ## Read Server (gh-tooling) -31 tools available via the `gh-tooling` MCP server. Requires `gh` CLI installed and authenticated. +Tools available via the `gh-tooling` MCP server. Requires `gh` CLI installed and authenticated. ### Shared Tool Parameters @@ -549,7 +549,7 @@ Use gh-tooling api_read with endpoint "search/issues" and jq_filter ".items[] | ## Write Server (gh-tooling-write) -25 tools available via the `gh-tooling-write` MCP server. Requires `enable_write_server: true` in `.mcp-gh-tooling.json`. +Tools available via the `gh-tooling-write` MCP server. Requires `enable_write_server: true` in `.mcp-gh-tooling.json`. ### Shared Tool Parameters From 40e92ca944ba227c5d9ec5ead990bedf476fe0d9 Mon Sep 17 00:00:00 2001 From: Martin Bens Date: Fri, 2 Oct 2026 20:36:44 +0200 Subject: [PATCH 03/14] refactor(github-mcp): give the shell library functions Google-style headers The libraries mixed two header styles: short `Args:`/`Sets:` comments and `#####`-bounded Google Shell Style blocks. Every function in hooks/scripts/lib/common.sh and mcp-server-gh/lib/*.sh that used the short form now has a block with Globals, Arguments, Outputs, and Returns, matching the blocks already there. Four headers contradicted their code and are corrected: load_mcp_config and block_tool gave php-tooling examples that do not exist in this plugin, _gh_resolve_owner_repo left the bare repo step out of its precedence list, and _gh_validate_path described a '..' segment check where the code refuses '..' anywhere in the path. The hook scripts also switch from #!/bin/bash to #!/usr/bin/env bash, like the server scripts. The hooks run as `bash