mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
* Remove mcp_config input in favor of --mcp-config in claude_args
BREAKING CHANGE: The mcp_config input has been removed. Users should now use --mcp-config flag in claude_args instead.
This simplifies the action's input surface area and aligns better with the Claude Code CLI interface. Users can still add multiple MCP configurations by using multiple --mcp-config flags.
Migration:
- Before: mcp_config: '{"mcpServers": {...}}'
- After: claude_args: '--mcp-config {"mcpServers": {...}}'
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add outer action MCP tests to workflow
- Add test-outer-action-inline-mcp job to test inline MCP config via claude_args
- Add test-outer-action-file-mcp job to test file-based MCP config via claude_args
- Keep base-action tests unchanged (they still use mcp_config parameter)
- Test that MCP tools are properly discovered and can be executed through the outer action
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix: Add Bun setup to outer action MCP test jobs
The test jobs for the outer action were failing because Bun wasn't installed.
Added Setup Bun step to both test-outer-action-inline-mcp and test-outer-action-file-mcp jobs.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add id-token permission to outer action MCP test jobs
The outer action needs id-token: write permission for OIDC authentication
when using the GitHub App. Added full permissions block to both
test-outer-action-inline-mcp and test-outer-action-file-mcp jobs.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use github_token parameter instead of id-token permission
Replace id-token: write permission with explicit github_token parameter
for both outer action MCP test jobs. This simplifies authentication by
using the provided GitHub token directly.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use RUNNER_TEMP environment variable consistently
Changed from GitHub Actions expression syntax to environment variable
for consistency with the rest of the workflow file.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use execution_file output from action instead of hardcoded path
Updated outer action test jobs to:
- Add step IDs (claude-inline-test, claude-file-test)
- Use the execution_file output from the action steps
- This is more reliable than hardcoding the output file path
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* tmp
* Fix MCP test assertions to match actual output format
Updated the test assertions to match the actual JSON structure:
- Tool calls are in assistant messages with type='tool_use'
- Tool results are in user messages with type='tool_result'
- The test tool returns 'Test tool response' not 'Hello from test tool'
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Make inline MCP test actually use the tool instead of just listing
Changed the inline MCP test to:
- Request that Claude uses the test tool (not just list it)
- Add --allowedTools to ensure the tool can be used
- Check that the tool was actually called and returned expected result
- Output the full JSON for debugging
This makes both tests (inline and file-based) consistent in their approach.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
292 lines
11 KiB
YAML
292 lines
11 KiB
YAML
name: Test MCP Servers
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
test-mcp-integration:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 #v2
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
bun install
|
|
cd base-action/test/mcp-test
|
|
bun install
|
|
|
|
- name: Run Claude Code with MCP test
|
|
uses: ./base-action
|
|
id: claude-test
|
|
with:
|
|
prompt: "List all available tools"
|
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
env:
|
|
# Change to test directory so it finds .mcp.json
|
|
CLAUDE_WORKING_DIR: ${{ github.workspace }}/base-action/test/mcp-test
|
|
|
|
- name: Check MCP server output
|
|
run: |
|
|
echo "Checking Claude output for MCP servers..."
|
|
|
|
# Parse the JSON output
|
|
OUTPUT_FILE="${RUNNER_TEMP}/claude-execution-output.json"
|
|
|
|
if [ ! -f "$OUTPUT_FILE" ]; then
|
|
echo "Error: Output file not found!"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Output file contents:"
|
|
cat $OUTPUT_FILE
|
|
|
|
# Check if mcp_servers field exists in the init event
|
|
if jq -e '.[] | select(.type == "system" and .subtype == "init") | .mcp_servers' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ Found mcp_servers in output"
|
|
|
|
# Check if test-server is connected
|
|
if jq -e '.[] | select(.type == "system" and .subtype == "init") | .mcp_servers[] | select(.name == "test-server" and .status == "connected")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ test-server is connected"
|
|
else
|
|
echo "✗ test-server not found or not connected"
|
|
jq '.[] | select(.type == "system" and .subtype == "init") | .mcp_servers' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if mcp tools are available
|
|
if jq -e '.[] | select(.type == "system" and .subtype == "init") | .tools[] | select(. == "mcp__test-server__test_tool")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ MCP test tool found"
|
|
else
|
|
echo "✗ MCP test tool not found"
|
|
jq '.[] | select(.type == "system" and .subtype == "init") | .tools' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "✗ No mcp_servers field found in init event"
|
|
jq '.[] | select(.type == "system" and .subtype == "init")' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
echo "✓ All MCP server checks passed!"
|
|
|
|
test-mcp-config-flag:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 #v2
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
bun install
|
|
cd base-action/test/mcp-test
|
|
bun install
|
|
|
|
- name: Debug environment paths (--mcp-config test)
|
|
run: |
|
|
echo "=== Environment Variables (--mcp-config test) ==="
|
|
echo "HOME: $HOME"
|
|
echo ""
|
|
echo "=== Expected Config Paths ==="
|
|
echo "GitHub action writes to: $HOME/.claude/settings.json"
|
|
echo "Claude should read from: $HOME/.claude/settings.json"
|
|
echo ""
|
|
echo "=== Actual File System ==="
|
|
ls -la $HOME/.claude/ || echo "No $HOME/.claude directory"
|
|
|
|
- name: Run Claude Code with --mcp-config flag
|
|
uses: ./base-action
|
|
id: claude-config-test
|
|
with:
|
|
prompt: "List all available tools"
|
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
mcp_config: '{"mcpServers":{"test-server":{"type":"stdio","command":"bun","args":["simple-mcp-server.ts"],"env":{}}}}'
|
|
env:
|
|
# Change to test directory so bun can find the MCP server script
|
|
CLAUDE_WORKING_DIR: ${{ github.workspace }}/base-action/test/mcp-test
|
|
|
|
- name: Check MCP server output with --mcp-config
|
|
run: |
|
|
echo "Checking Claude output for MCP servers with --mcp-config flag..."
|
|
|
|
# Parse the JSON output
|
|
OUTPUT_FILE="${RUNNER_TEMP}/claude-execution-output.json"
|
|
|
|
if [ ! -f "$OUTPUT_FILE" ]; then
|
|
echo "Error: Output file not found!"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Output file contents:"
|
|
cat $OUTPUT_FILE
|
|
|
|
# Check if mcp_servers field exists in the init event
|
|
if jq -e '.[] | select(.type == "system" and .subtype == "init") | .mcp_servers' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ Found mcp_servers in output"
|
|
|
|
# Check if test-server is connected
|
|
if jq -e '.[] | select(.type == "system" and .subtype == "init") | .mcp_servers[] | select(.name == "test-server" and .status == "connected")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ test-server is connected"
|
|
else
|
|
echo "✗ test-server not found or not connected"
|
|
jq '.[] | select(.type == "system" and .subtype == "init") | .mcp_servers' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if mcp tools are available
|
|
if jq -e '.[] | select(.type == "system" and .subtype == "init") | .tools[] | select(. == "mcp__test-server__test_tool")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ MCP test tool found"
|
|
else
|
|
echo "✗ MCP test tool not found"
|
|
jq '.[] | select(.type == "system" and .subtype == "init") | .tools' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "✗ No mcp_servers field found in init event"
|
|
jq '.[] | select(.type == "system" and .subtype == "init")' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
echo "✓ All MCP server checks passed with --mcp-config flag!"
|
|
|
|
# Test the outer action with inline MCP config
|
|
test-outer-action-inline-mcp:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 #v2
|
|
|
|
- name: Install test MCP server dependencies
|
|
run: |
|
|
cd base-action/test/mcp-test
|
|
bun install
|
|
|
|
- name: Test outer action with inline MCP config
|
|
uses: ./
|
|
id: claude-inline-test
|
|
with:
|
|
prompt: "Use the mcp__test-server__test_tool to test the MCP integration"
|
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
claude_args: |
|
|
--mcp-config '{"mcpServers":{"test-server":{"type":"stdio","command":"bun","args":["base-action/test/mcp-test/simple-mcp-server.ts"],"env":{}}}}'
|
|
--allowedTools mcp__test-server__test_tool
|
|
|
|
- name: Check execution output
|
|
run: |
|
|
echo "Checking if MCP test tool was used..."
|
|
OUTPUT_FILE="${{ steps.claude-inline-test.outputs.execution_file }}"
|
|
|
|
if [ ! -f "$OUTPUT_FILE" ]; then
|
|
echo "Error: Output file not found!"
|
|
exit 1
|
|
fi
|
|
|
|
cat $OUTPUT_FILE
|
|
|
|
# Check if the tool was actually called - looking in assistant messages
|
|
if jq -e '.[] | select(.type == "assistant" and .message.content) | .message.content[] | select(.type == "tool_use" and .name == "mcp__test-server__test_tool")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ MCP test tool was called"
|
|
|
|
# Check the tool result - looking for the user message with tool_result
|
|
if jq -e '.[] | select(.type == "user" and .message.content[0].type == "tool_result") | .message.content[0].content[0].text | contains("Test tool response")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ MCP test tool returned expected result"
|
|
else
|
|
echo "✗ MCP test tool result not as expected"
|
|
echo "Tool results in output:"
|
|
jq '.[] | select(.type == "user") | .message.content[]? | select(.type == "tool_result")' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "✗ MCP test tool was not called"
|
|
echo "Tools used:"
|
|
jq '.[] | select(.type == "assistant" and .message.content) | .message.content[] | select(.type == "tool_use") | .name' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# Test the outer action with file-based MCP config
|
|
test-outer-action-file-mcp:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 #v2
|
|
|
|
- name: Install test MCP server dependencies
|
|
run: |
|
|
cd base-action/test/mcp-test
|
|
bun install
|
|
|
|
- name: Create MCP config file
|
|
run: |
|
|
cat > /tmp/test-mcp-config.json << 'EOF'
|
|
{
|
|
"mcpServers": {
|
|
"test-server": {
|
|
"type": "stdio",
|
|
"command": "bun",
|
|
"args": ["base-action/test/mcp-test/simple-mcp-server.ts"],
|
|
"env": {}
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
|
|
- name: Test outer action with file-based MCP config
|
|
uses: ./
|
|
id: claude-file-test
|
|
with:
|
|
prompt: "Use the mcp__test-server__test_tool to test the MCP integration"
|
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
claude_args: |
|
|
--mcp-config /tmp/test-mcp-config.json
|
|
--allowedTools mcp__test-server__test_tool
|
|
|
|
- name: Check tool usage
|
|
run: |
|
|
echo "Checking if MCP test tool was used..."
|
|
OUTPUT_FILE="${{ steps.claude-file-test.outputs.execution_file }}"
|
|
|
|
if [ ! -f "$OUTPUT_FILE" ]; then
|
|
echo "Error: Output file not found!"
|
|
exit 1
|
|
fi
|
|
|
|
cat $OUTPUT_FILE
|
|
|
|
# Check if the tool was actually called - looking in assistant messages
|
|
if jq -e '.[] | select(.type == "assistant" and .message.content) | .message.content[] | select(.type == "tool_use" and .name == "mcp__test-server__test_tool")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ MCP test tool was called"
|
|
|
|
# Check the tool result - looking for the user message with tool_result
|
|
if jq -e '.[] | select(.type == "user" and .message.content[0].type == "tool_result") | .message.content[0].content[0].text | contains("Test tool response")' "$OUTPUT_FILE" > /dev/null; then
|
|
echo "✓ MCP test tool returned expected result"
|
|
else
|
|
echo "✗ MCP test tool result not as expected"
|
|
echo "Tool results in output:"
|
|
jq '.[] | select(.type == "user") | .message.content[]? | select(.type == "tool_result")' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "✗ MCP test tool was not called"
|
|
echo "Tools used:"
|
|
jq '.[] | select(.type == "tool") | .name' "$OUTPUT_FILE"
|
|
exit 1
|
|
fi
|