Skip to content

feat(mcp): zero-dependency MCP server + agent-integration guide - #71

Open
Chosen9115 wants to merge 1 commit into
mainfrom
feature/mcp-server-and-integration-doc
Open

feat(mcp): zero-dependency MCP server + agent-integration guide#71
Chosen9115 wants to merge 1 commit into
mainfrom
feature/mcp-server-and-integration-doc

Conversation

@Chosen9115

Copy link
Copy Markdown
Owner

What & why

Make OpenSOP consumable by any agent through the interfaces they already speak — without coupling the standard to a single runtime. OpenSOP is a neutral standard, so the right "play well with X" surface is generic (MCP + the CLI as a shell tool), and runtime-specific glue stays on the consumer's side.

Two ways for an agent to drive OpenSOP, both local-first:

  • Path A — the CLI as a plain shell tool. Any agent that can run a command shells out to opensop … --json. Zero integration code (works with terminal-backed agents, cron, a Makefile).
  • Path B — the MCP server. For MCP-native agents (Claude Desktop, etc.), mcp/opensop-mcp exposes the same agent loop as MCP tools over stdio.

What's here

  • mcp/opensop-mcp — a single bash file. Deps: bash + jq only (same as the CLI; no pip, no npm, no build step — the file is the binary). Speaks MCP stdio (newline-delimited JSON-RPC 2.0) and shells out to the local CLI. Exposes the full agent loop — discover → preview → run → resume → audit — as 9 tools: opensop_list, opensop_search, opensop_suggest, opensop_dry_run, opensop_run, opensop_status, opensop_submit, opensop_show, opensop_runs.
    • Local-first: OPENSOP_SERVER opts into a remote /sop/* server; unset = local.
    • Trust boundary: opensop_run/opensop_submit execute local processes (arbitrary shell, same posture as a Makefile). OPENSOP_MCP_READONLY hides and refuses them — safe default for untrusted corpora.
    • CLI errors come back as isError:true carrying the {error,message,hint} envelope, so agents see structured failures.
  • docs/CLAUDE-INTEGRATION.md — the canonical agent-integration guide (this also fixes the previously-dangling link from cli/README.md). The agent loop with concrete commands, Path A vs Path B, Claude Desktop + generic-client config snippets, a 9-row tool reference table, and the trust/safety section.
  • mcp/README.md + discoverability pointers from README.md and docs/AGENTS.md.
  • mcp/test/test.sh — golden suite, 17 cases: initialize handshake (protocolVersion echo, serverInfo), tools/list + readonly filtering, every tool's happy path, run→status→runs→show loop, error passthrough, glob-safe search, notifications-get-no-reply, unknown method/tool, missing-arg.

Security review (done before this PR)

An adversarial pass confirmed no command injection — there is no eval anywhere in the server or the CLI; all tool arguments reach the CLI as array elements, never a shell string. Three issues were found and fixed, each now regression-covered:

  • HIGHopensop_search keyword splitting used an unquoted kwarr=($kws), which glob-expanded */foo* against the CWD → now read -ra (word-split, no pathname expansion).
  • MEDIUM — id-less notifications received spurious responses for known methods (JSON-RPC violation) → HAS_ID guard so notifications never get a reply.
  • LOWerrf=$(mktemp) was unguarded under set -e → guarded, degrades to an isError result.

Test plan

  • bash -n mcp/opensop-mcp — clean.
  • bash mcp/test/test.sh17 PASS, ALL PASS, exit 0.
  • bash cli/test/test.sh289 PASS (this PR doesn't touch the CLI; confirms no disturbance).
  • Manual end-to-end: initialize → tools/list → suggest/search → run (status completed) → status → readonly hides run/submit. All correct.

Self-rating

Correctness 9 · simplicity 9 (single-file, no new dependency class) · test coverage 9 (17 protocol/tool/error cases) · security 9 (adversarial review + fixes + regression tests) · spec fidelity 10 (no /sop/* contract change; wraps existing CLI) · public-repo hygiene 10 (placeholders only; no PII/secrets/internal identifiers).

🤖 Generated with Claude Code

Make OpenSOP consumable by any agent through the interfaces they already
speak, without coupling the standard to any one runtime.

- mcp/opensop-mcp — a single bash file (deps: bash + jq only, same as the
  CLI; no pip, no npm, no build) that speaks MCP stdio (newline-delimited
  JSON-RPC 2.0) and shells out to the local CLI. Exposes the full agent loop
  as 9 tools: list, search, suggest, dry_run, run, status, submit, show, runs.
  Local-first (OPENSOP_SERVER opts into a remote). Trust boundary: run/submit
  execute local processes (arbitrary shell) — OPENSOP_MCP_READONLY hides and
  refuses them for untrusted corpora.
- docs/CLAUDE-INTEGRATION.md — the canonical "how any agent consumes OpenSOP"
  guide (fixes the previously-dangling link from cli/README.md). Covers Path A
  (CLI as a plain shell tool — works with any terminal-backed agent) and Path B
  (the MCP server) with Claude Desktop / generic-client config snippets and a
  tool reference table.
- mcp/README.md, plus discoverability pointers from README.md and docs/AGENTS.md.
- mcp/test/test.sh — golden suite (17 cases): initialize handshake, tools/list
  + readonly filtering, every tool's happy path, error passthrough (isError),
  glob-safe search, notifications-get-no-reply, unknown method/tool, missing args.

Security-reviewed before merge: no command injection (no eval anywhere);
fixed glob expansion in search keyword splitting (read -ra, not unquoted
$kws), JSON-RPC notification replies (HAS_ID guard), and an unguarded mktemp
under set -e. All three are regression-covered.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant