Reproduce a single LinkedIn-MCP issue locally on the current branch against the real authenticated LinkedIn session at ~/.linkedin-mcp/profile/, using the MCP streamable-http server. Captures the exact failure mode (tool output, error, missing data) and maps it back to the scraper code path. Use when the user says "reproduce
74
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Goal: take an issue number, run the exact failing tool call against the real LinkedIn via the local MCP server, and produce concrete evidence — output JSON, error message, partial state — that confirms or refutes the bug on the current branch. Always use the authenticated profile already at ~/.linkedin-mcp/profile/. Never mock.
# Accept "442", "#442", or "https://github.com/.../issues/442" — extract the digits only
NUM=$(echo "$ARGUMENTS" | sed -E 's|.*/||; s|#||g' | grep -oE '^[0-9]+' | head -1)
[ -z "$NUM" ] && { echo "Invalid input: '$ARGUMENTS'. Pass an issue number or URL." >&2; exit 1; }
REPO=stickerdaniel/linkedin-mcp-server
gh issue view $NUM --repo $REPO --commentsFrom the issue body extract:
get_person_profile, connect_with_person, search_jobs, …). The issue templates ask for this explicitly.Map the tool to code so you know where to look if the repro confirms the bug:
linkedin_mcp_server/tools/<surface>.py — MCP entrypoint and arg validationlinkedin_mcp_server/scraping/<feature>.py — actual scraping (extractor.py, connection.py, feed.py, inbox.py, …)linkedin_mcp_server/scraping/fields.py — PERSON_SECTIONS / COMPANY_SECTIONS (each entry = one navigation)tests/test_scraping.py covering the same surfaceState out loud before running anything: "Reproducing tool X with args Y on branch <current> — expecting <failure mode from issue>."
git status --porcelain | head -5 # workspace must be clean
git log -1 --oneline # record the SHA we're testing
ls ~/.linkedin-mcp/profile/ | head -3 # profile must existIf the workspace is dirty, ask the user before continuing — they may have local changes that affect the repro. If the profile is missing or stale, run uv run -m linkedin_mcp_server --login once and only once per skill invocation.
Always uv run, never uvx — the running server must reflect the current workspace (per CLAUDE.md → Verifying Bug Reports).
Default port 8000 is commonly taken by other dev servers (workspace-mcp, etc.). Probe for a free port from 8765 upward instead of failing late on address already in use:
# Probe a free port starting at 8765
PORT=8765
while lsof -nP -iTCP:$PORT -sTCP:LISTEN >/dev/null 2>&1; do PORT=$((PORT+1)); done
echo $PORT > /tmp/repro-$NUM.port
# Start in background
uv run -m linkedin_mcp_server --transport streamable-http --port $PORT --log-level INFO > /tmp/repro-$NUM.log 2>&1 &
SERVER_PID=$!
echo $SERVER_PID > /tmp/repro-$NUM.pid
# Wait for the port to actually start LISTENing instead of a blind sleep.
# Cap at ~30s so a stuck startup doesn't hang the run.
for i in $(seq 1 30); do
lsof -nP -iTCP:$PORT -sTCP:LISTEN >/dev/null 2>&1 && break
kill -0 $SERVER_PID 2>/dev/null || { echo "Server died during startup. Tail of /tmp/repro-$NUM.log:" >&2; tail -20 /tmp/repro-$NUM.log >&2; exit 1; }
sleep 1
done
lsof -nP -iTCP:$PORT -sTCP:LISTEN >/dev/null 2>&1 || { echo "Server never bound port $PORT after 30s" >&2; tail -20 /tmp/repro-$NUM.log >&2; exit 1; }
echo "Server PID: $SERVER_PID Port: $PORT Ready"If /tmp/repro-$NUM.log shows login failure or browser issues, stop and report, do not try to brute-force around it.
PORT=$(cat /tmp/repro-$NUM.port)
curl -s -D /tmp/repro-$NUM-headers -X POST http://127.0.0.1:$PORT/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"repro-issue","version":"1.0"}}}' > /dev/null
SESSION_ID=$(grep -i 'Mcp-Session-Id' /tmp/repro-$NUM-headers | awk '{print $2}' | tr -d '\r')
[ -z "$SESSION_ID" ] && { echo "MCP initialize returned no Mcp-Session-Id. Tail of /tmp/repro-$NUM.log:" >&2; tail -20 /tmp/repro-$NUM.log >&2; kill $SERVER_PID 2>/dev/null; exit 1; }
curl -s -X POST http://127.0.0.1:$PORT/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: $SESSION_ID" \
-d '{"jsonrpc":"2.0","id":2,"method":"notifications/initialized","params":{}}' > /dev/nullThe notifications/initialized post often returns {"error":{"code":-32602,"message":"Invalid request parameters"}} and the server log shows a long pydantic ClientRequest validation dump. This is harmless. The session is still valid and tools/call works on the same SESSION_ID. Do not retry, do not treat as a session failure.
Substitute the tool name and arguments from Phase 1 verbatim. Save the response to a stable path and persist the request metadata so /3-verify-pr-fix can replay the exact same call without guessing.
TOOL="<TOOL>" # e.g. get_person_profile
ARGS_JSON='{<ARGS>}' # e.g. {"linkedin_username":"williamhgates","sections":"basic_info"}
# Persist what we are about to call so the verifier can re-run identically
jq -n --arg t "$TOOL" --argjson a "$ARGS_JSON" '{tool: $t, arguments: $a}' \
> /tmp/repro-issue-$NUM-meta.json
curl -s -X POST http://127.0.0.1:$PORT/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: $SESSION_ID" \
-d "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"$TOOL\",\"arguments\":$ARGS_JSON}}" \
| tee /tmp/repro-issue-$NUM-main.json | head -200If the issue doesn't pin a concrete target, pick a stable public one:
williamhgates, plus one non-English target if locale matters.microsoft, plus one German/EU company if locale matters.Run the call twice if the result looks flaky (network, slow render) — LinkedIn rate-limit / partial-render can mask real bugs.
Read /tmp/repro-issue-$NUM-main.json and the server log. Pick one verdict:
git log --oneline -20 and last release tag) or the issue may be environment-specific (different LinkedIn account, different locale).Locate the failure in code:
grep -rn "def <tool>" linkedin_mcp_server/scraping/fields.py for the section's URL and verify it's correct.kill $SERVER_PID 2>/dev/null
wait $SERVER_PID 2>/dev/null
rm -f /tmp/repro-$NUM-headers /tmp/repro-$NUM.log /tmp/repro-$NUM.port /tmp/repro-$NUM.pid
# Keep /tmp/repro-issue-$NUM-main.json (response baseline) and
# /tmp/repro-issue-$NUM-meta.json (tool + args) — /3-verify-pr-fix uses both.Report format:
**#<N>** — <one-line issue summary>
**Branch / SHA:** <branch> @ <short-sha>
**Tool / args:** <TOOL>(<ARGS>)
**Verdict:** <Reproduced ✓ | Reproduced different mode ⚠ | Not reproduced ✗ | Inconclusive>
**Evidence:** <2–4 lines of the actual tool output that proves the verdict>
**Likely code path:** <file:line> — <one-line why>
**Baseline saved at:** /tmp/repro-issue-<N>-main.json (used by /3-verify-pr-fix)
**Next:** <suggest /3-verify-pr-fix N if a candidate PR exists | suggest fix sketch | suggest closing as already-fixed>uv run, not uvx. The server must reflect the workspace.6d36970
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.