Skip to main content

field-test

Exercise git tools, resources, and prompts against a live HTTP server via MCP JSON-RPC over curl. Starts the server, surfaces the catalog, runs real and adversarial inputs, and produces a tight report with concrete findings and numbered follow-up options. Use after adding or modifying definitions, or when the user asks to test, try out, or verify the MCP surface.

설치로 이동

소스 정보

저장소
cyanheads/git-mcp-server
최근 소스 활동
2026년 4월 23일 21:27
감지된 SKILL.md 언어
영어
스타
240
포크
56

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
field-test
description
Exercise git tools, resources, and prompts against a live HTTP server via MCP JSON-RPC over curl. Starts the server, surfaces the catalog, runs real and adversarial inputs, and produces a tight report with concrete findings and numbered follow-up options. Use after adding or modifying definitions, or when the user asks to test, try out, or verify the MCP surface.
metadata
{"author":"cyanheads","version":"1.0","type":"debug"}
## Context Unit tests verify handler logic with mocked context. Field testing exercises the real HTTP transport with real JSON-RPC: starts the server, calls `initialize`, surfaces the catalog, runs inputs, and checks what a client actually sees. It catches what unit tests miss — awkward input shapes, unhelpful errors, missing `responseFormatter` output, drift between `structuredContent` and `content[]`, edge-case surprises, and git-specific behavior around conflicts, bare repos, protected branches, working directory state, etc. **Actively call the tools. Don't read code and guess.** For git tools specifically: prefer a throwaway test repo (`/tmp/field-test-repo` initialized with `git init` and a seed commit) over the project itself so state changes are bounded and easy to clean up. --- ## Steps ### 1. Start the server Write the helper to `/tmp/mcp-field-test.sh` once, then source it in every subsequent Bash call. Helper keeps PID / URL / session id in `/tmp/mcp-field-test.env` so state survives across tool invocations. ```bash cat > /tmp/mcp-field-test.sh <<'HELPER_EOF' #!/bin/bash # Field-test helper: manage an MCP HTTP server + JSON-RPC session across shell calls. STATE_FILE="/tmp/mcp-field-test.env" [ -f "$STATE_FILE" ] && . "$STATE_FILE" mcp_start() { local dir="${1:-$PWD}" echo "building $dir ..." (cd "$dir" && bun run rebuild) >/tmp/mcp-build.log 2>&1 \ || { echo "BUILD FAILED — see /tmp/mcp-build.log"; return 1; } echo "starting server ..." (cd "$dir" && bun run start:http) >/tmp/mcp-server.log 2>&1 & local pid=$! local line="" for _ in $(seq 1 40); do line=$(grep -Eo 'listening at http://[^" ]+/mcp' /tmp/mcp-server.log | head -1) [ -n "$line" ] && break sleep 0.25 done if [ -z "$line" ]; then echo "server failed to start — see /tmp/mcp-server.log" kill "$pid" 2>/dev/null return 1 fi local url="${line#listening at }" local port; port=$(echo "$url" | sed -E 's|.*:([0-9]+)/.*|\1|') cat > "$STATE_FILE" <<EOF export MCP_PID=$pid export MCP_URL=$url export MCP_PORT=$port EOF . "$STATE_FILE" echo "ready pid=$pid url=$url" } mcp_init() { [ -z "$MCP_URL" ] && { echo "run mcp_start first"; return 1; } local hdr="/tmp/mcp-init-headers.txt" curl -sS -D "$hdr" -X POST "$MCP_URL" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"field-test","version":"1.0"}}}' >/dev/null local sid; sid=$(grep -i '^mcp-session-id:' "$hdr" | awk '{print $2}' | tr -d '\r\n') [ -z "$sid" ] && { echo "no session id returned"; return 1; } cat > "$STATE_FILE" <<EOF export MCP_PID=$MCP_PID export MCP_URL=$MCP_URL export MCP_PORT=$MCP_PORT export MCP_SID=$sid EOF . "$STATE_FILE" curl -sS -X POST "$MCP_URL" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "Mcp-Session-Id: $sid" \ -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' >/dev/null echo "session=$sid" } # Usage: mcp_call METHOD [JSON_PARAMS] # Prints the JSON-RPC response (SSE framing stripped). Pipe to `jq`. mcp_call() { [ -z "$MCP_SID" ] && { echo "run mcp_init first"; return 1; } local method="$1"; local params="${2:-}" local body if [ -z "$params" ]; then body=$(printf '{"jsonrpc":"2.0","id":%d,"method":"%s"}' "$RANDOM" "$method") else body=$(printf '{"jsonrpc":"2.0","id":%d,"method":"%s","params":%s}' "$RANDOM" "$method" "$params") fi curl -sS -X POST "$MCP_URL" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "Mcp-Session-Id: $MCP_SID" \ -d "$body" | sed -n 's/^data: //p' } mcp_stop() { [ -n "$MCP_PID" ] && kill "$MCP_PID" 2>/dev/null rm -f "$STATE_FILE" echo "stopped" } HELPER_EOF . /tmp/mcp-field-test.sh mcp_start /Users/casey/Developer/github/git-mcp-server ``` **Notes** - `MCP_HTTP_PORT` is a _starting_ port — the server auto-increments if taken. Helper parses the real URL from the log (`HTTP transport listening at ...`). - If `bun run rebuild` fails, stop. Don't field-test broken code — fix the build first. - If a server is already listening on the project's port (`lsof -i :<port>`), confirm with the user before killing it; it may be their own session. - `MCP_AUTH_MODE=none` is the default dev configuration — no auth headers needed. ### 2. Initialize the session ```bash . /tmp/mcp-field-test.sh mcp_init ``` Runs `initialize`, captures the session id, sends `notifications/initialized`. ### 3. Prepare a test repository Most git tools require a working directory. Create a sandboxed repo once: ```bash TEST_REPO=/tmp/field-test-repo rm -rf "$TEST_REPO" && mkdir -p "$TEST_REPO" (cd "$TEST_REPO" && \ git init -q && \ git config user.email "field-test@example.com" && \ git config user.name "Field Test" && \ echo "initial" > README.md && \ git add README.md && \ git commit -q -m "initial commit") echo "test repo ready at $TEST_REPO" ``` Pass `$TEST_REPO` as the `path` argument in tool calls (never `.`, since that resolves to session state). For tests that don't need a repo (e.g. `git_clone`, `git_set_working_dir`), use `/tmp/field-test-dest` or similar. ### 4. Surface the catalog ```bash . /tmp/mcp-field-test.sh mcp_call tools/list | jq '.result.tools[] | {name, description, inputSchema}' mcp_call resources/list | jq '.result.resources[] | {uri, name, mimeType}' mcp_call prompts/list | jq '.result.prompts[] | {name, description, arguments}' ``` Present a compact catalog to the user: each definition's name + 1-line description. Flag vague or missing descriptions as you go — those feed into the report. ### 5. Plan the test pass **Budget.** This server exposes ~29 git tools. Don't run every category against every tool — the cross-product is infeasible. Apply the **universal battery** to everything; apply **situational categories** only when the tool triggers them. **Universal battery — run on every tool** | Category | What to verify | | :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ | | Happy path | One realistic input against `$TEST_REPO`. Output shape matches `outputSchema`. `content[]` text reads clearly to a human. | | `structuredContent` ↔ `content[]` parity | Every field in `structuredContent` is surfaced in the text. Parity gap = client-specific blindness. | | Input error | One invalid input (wrong type or missing required). Error text says _what_, _why_, _how to fix_. | **Situational — add only when triggered** | Trigger | Add category | | :--------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | `verbosity` / `fields` / `include` parameter | Field selection: verify `minimal` / `standard` / `full` actually differ | | Array return with `query` / `filter` inputs (e.g. `git_log`) | Empty result: does response explain _why_ (echo criteria, suggest broadening)? | | Destructive flags (`--hard`, `--force`, `git_clean`) | Confirm guard: does the tool require explicit flag to proceed? | | Conflict-producing operations (`git_merge`, `git_rebase`, `git_cherry_pick`, `git_pull`) | Construct a conflict on purpose; confirm `{ success: true, conflicts: true, conflictedFiles: [...] }` shape | | Requires remote (`git_fetch`, `git_pull`, `git_push`, `git_clone`) | Either point at a local bare repo file:// URL or skip with a note | | Bare-repo-only behavior (`git_init --bare`) | Verify `isBare: true` surfaces; verify `git_add`/`git_commit` reject | | `annotations.readOnlyHint: true` | Confirm no mutation happened | | Session working directory (`path: "."`) | Run `git_set_working_dir`, then a read-only tool with `path: "."` to confirm resolution | | Chained workflows (status → add → commit → log) | Run one representative chain end-to-end | **Resources.** `git-working-directory.resource.ts`: happy path, unset state (before `git_set_working_dir` is called). **Prompts.** `git-wrapup.prompt.ts`: happy path, skim message quality. **Sampling strategy.** Run the universal battery on all 29 tools, but pick roughly 30–40% for situational testing. Weight toward: write-shaped tools, tools with complex schemas, tools that integrate multiple operations (`git_merge`, `git_rebase`, `git_stash`, `git_worktree`). List which ones you skipped in the report. **External state.** - `git_push` / `git_clone` against real remotes: use `file://` URLs to local bare repos, or skip with a note. - Tools that write to real external systems should never touch the user's real `origin`. ### 6. Execute Use `TaskCreate` — one task per tool (or logical group). Mark complete as you go. Don't batch. For each call, capture: input sent, response (trim huge payloads to files), whether `isError: true` appeared, anything surprising (slow response, parity drift, unhelpful text, crash). **Interpreting responses**
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기