Skip to content

Using stdio transport for custom mcp config isn't working #130

@a-stjohn

Description

@a-stjohn

Describe the bug
I've written a custom mcp server in python using fastmcp>=2.6.1 and uv as the python project manager. I've tested it multiple ways locally and everything works as intended. However, when trying to get it to work in claude-code-action, it doesn't work. The only helpful message I can find in my Github workflow output is:

  "mcp_servers": [
    {
      "name": "current_time_test_server",
      "status": "failed"
    },
    {
      "name": "github_file_ops",
      "status": "connected"
    },
    {
      "name": "sequential-thinking",
      "status": "connected"
    },
    {
      "name": "github",
      "status": "connected"
    }
  ]

I'm using AWS Bedrock and have verified that's working correctly (with the connection to custom MCP failing). I even added a debug step and can successfully start the mcp server using uv within the runner. Is there something I'm missing or is this a bug?

To Reproduce
Steps to reproduce the behavior:

  1. Install Claude App in your repo
  2. Add mcp server python code as listed in the additional context section
  3. Add workflow yaml file that's listed (uses aws bedrock and a personal Github app)
  4. Observe that the current_time_test_server fails to connect in the Github action output.

Expected behavior
Expect claude-code-action to successfully connect to custom mcp server using stdio and be able to use the tools (get_current_time) in this case.

Screenshots

Image

Workflow yml file

name: Claude PR Action

permissions:
  contents: write
  pull-requests: write
  issues: write
  id-token: write

on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]

jobs:
  claude-pr:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Generate GitHub App token
        id: app-token
        uses: actions/create-github-app-token@v2
        with:
          app-id: ${{ secrets.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}

      - name: Configure AWS Credentials (OIDC)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Install uv
        uses: astral-sh/setup-uv@v5
        with:
          version: "0.7.10"

      - name: Sync uv Project
        run: |
          uv sync

      - name: Debug
        run: |
          pwd
          ls -la
          uv run time_test_mcp.py &

      - name: Claude Code Action Official
        uses: anthropics/claude-code-action@beta
        with:
          timeout_minutes: "10"
          use_bedrock: "true"
          model: us.anthropic.claude-sonnet-4-20250514-v1:0
          github_token: ${{ steps.app-token.outputs.token }}
          mcp_config: |
            {
              "mcpServers": {
                "current_time_test_server": {
                  "command": "uv",
                  "args": [
                    "run",
                    "time_test_mcp.py"
                  ]
                },
                "sequential-thinking": {
                  "command": "npx",
                  "args": [
                    "-y",
                    "@modelcontextprotocol/server-sequential-thinking"
                  ]
                }
              }
            }
          allowed_tools: "test_time_server___get_current_time"

API Provider

[ ] Anthropic First-Party API (default)
[ x] AWS Bedrock
[ ] GCP Vertex

Additional context
python code for mcp server:

from datetime import datetime, timezone
from typing import Any

from fastmcp import FastMCP

mcp = FastMCP(
    name="Time Test MCP",
    instructions="""This server provides a simple tool to get the current time.
    
    Use the `get_current_time` tool to retrieve the current UTC time regardless of timezone.
    """,
)


@mcp.tool(
    name="get_current_time",
    description="Get the current UTC time regardless of timezone.",
)
async def get_current_time() -> dict[str, Any]:
    """
    Get the current UTC time.

    Returns:
        dict[str, Any]: A dictionary containing:
            - utc_time: Current UTC time in ISO format
            - timestamp: Unix timestamp
            - formatted_time: Human-readable UTC time string
    """
    try:
        # Get current UTC time
        now_utc = datetime.now(timezone.utc)

        # Format the response
        time_info = {
            "utc_time": now_utc.isoformat(),
            "timestamp": now_utc.timestamp(),
            "formatted_time": now_utc.strftime("%Y-%m-%d %H:%M:%S UTC"),
        }

        return time_info

    except Exception as e:
        # Handle any unexpected errors
        return {
            "error": f"Failed to get current time: {str(e)}",
            "utc_time": None,
            "timestamp": None,
            "formatted_time": None,
        }


def main():
    # Run the MCP server using stdio transport
    mcp.run(transport="stdio")


if __name__ == "__main__":
    main()

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions