Skip to content

Forward headers #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jsulopzs opened this issue Apr 19, 2025 · 6 comments
Closed

Forward headers #82

jsulopzs opened this issue Apr 19, 2025 · 6 comments
Labels
enhancement New feature or request

Comments

@jsulopzs
Copy link

jsulopzs commented Apr 19, 2025

I'm currently using mcp-proxy to call the mcp server running on fastapi_mcp.

The header with the bearer token is shown at first when connecting to the mcp endpoint. However, when the mcp host calls the tools, the header doesn't include the bearer token.

Checkout the logs:

INFO:     127.0.0.1:49358 - "POST /mcp/messages/?session_id=b88f9bf746c540b1ba08d8cfa7a9d123 HTTP/1.1" 202 Accepted
2025-04-19 16:29:18,535 - fastapi_mcp.transport.sse - DEBUG - Sending message to writer from background task: root=JSONRPCRequest(method='tools/list', params=None, jsonrpc='2.0', id=5)
2025-04-19 16:29:18,536 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest
2025-04-19 16:29:53,000 - mcp-clickhouse-fastapi - DEBUG - Incoming request: POST http://localhost:8080/mcp/messages/?session_id=b88f9bf746c540b1ba08d8cfa7a9d123
2025-04-19 16:29:53,000 - mcp-clickhouse-fastapi - DEBUG - Headers: Headers({'host': 'localhost:8080', 'accept': '*/*', 'accept-encoding': 'gzip, deflate', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.28.1', 'authorization': 'Bearer d315c4c3-321c-43c2-89de-da4cc264ce4c', 'content-length': '96', 'content-type': 'application/json'})
2025-04-19 16:29:53,000 - mcp-clickhouse-fastapi - DEBUG - Captured auth header: Bearer d315c4c3-321c-43c2-89de-da4cc264ce4c
2025-04-19 16:29:53,001 - fastapi_mcp.transport.sse - DEBUG - Handling POST message with FastAPI patterns
2025-04-19 16:29:53,001 - fastapi_mcp.transport.sse - DEBUG - Parsed session ID: b88f9bf7-46c5-40b1-ba08-d8cfa7a9d123
2025-04-19 16:29:53,002 - fastapi_mcp.transport.sse - DEBUG - Received JSON: {"method":"tools/call","params":{"name":"list_databases","arguments":{}},"jsonrpc":"2.0","id":6}
2025-04-19 16:29:53,002 - fastapi_mcp.transport.sse - DEBUG - Validated client message: root=JSONRPCRequest(method='tools/call', params={'name': 'list_databases', 'arguments': {}}, jsonrpc='2.0', id=6)
2025-04-19 16:29:53,002 - fastapi_mcp.transport.sse - DEBUG - Accepting message, will send in background
2025-04-19 16:29:53,002 - mcp-clickhouse-fastapi - DEBUG - Response status: 202
INFO:     127.0.0.1:49676 - "POST /mcp/messages/?session_id=b88f9bf746c540b1ba08d8cfa7a9d123 HTTP/1.1" 202 Accepted
2025-04-19 16:29:53,003 - fastapi_mcp.transport.sse - DEBUG - Sending message to writer from background task: root=JSONRPCRequest(method='tools/call', params={'name': 'list_databases', 'arguments': {}}, jsonrpc='2.0', id=6)
2025-04-19 16:29:53,003 - mcp.server.lowlevel.server - INFO - Processing request of type CallToolRequest
2025-04-19 16:29:53,004 - fastapi_mcp.server - DEBUG - Making GET request to http://localhost:8080/databases
2025-04-19 16:29:53,009 - mcp-clickhouse-fastapi - DEBUG - Incoming request: GET http://localhost:8080/databases
2025-04-19 16:29:53,009 - mcp-clickhouse-fastapi - DEBUG - Headers: Headers({'host': 'localhost:8080', 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br, zstd', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.28.1'})
2025-04-19 16:29:53,010 - mcp-clickhouse-fastapi - INFO - Request details: method=GET, url=http://localhost:8080/databases, headers=Headers({'host': 'localhost:8080', 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br, zstd', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.28.1'}), body=b''
2025-04-19 16:29:53,010 - mcp-clickhouse-fastapi - INFO - Request headers: Headers({'host': 'localhost:8080', 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br, zstd', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.28.1'})
2025-04-19 16:29:53,010 - mcp-clickhouse-fastapi - WARNING - Missing Authorization header
2025-04-19 16:29:53,010 - mcp-clickhouse-fastapi - DEBUG - Response status: 401
INFO:     127.0.0.1:49678 - "GET /databases HTTP/1.1" 401 Unauthorized
2025-04-19 16:29:53,011 - httpx - INFO - HTTP Request: GET http://localhost:8080/databases "HTTP/1.1 401 Unauthorized"
2025-04-19 16:29:53,012 - fastapi_mcp.server - ERROR - Error calling list_databases
Traceback (most recent call last):
  File "/Users/sota/miniforge3/envs/work/lib/python3.13/site-packages/fastapi_mcp/server.py", line 272, in _execute_api_tool
    raise Exception(
        f"Error calling {tool_name}. Status code: {response.status_code}. Response: {response.text}"
    )
Exception: Error calling list_databases. Status code: 401. Response: {"detail":"Unauthorized"}

How to make the headers defined in the mcp.json be forwarded on any request?

@jsulopzs jsulopzs added the enhancement New feature or request label Apr 19, 2025
@YoshitakaOyama
Copy link

Thank you for this great library.

I am also experiencing the same problem.

I am making a request with a header from client sied, but it seems that the header value is not being referenced on the server side.

@jsulopzs
Copy link
Author

In case it might be of help, I got it to work with the following code, which creates an AuthClient to update the authorization header. This client will be passed on to the http middleware.

# Create FastAPI app
app = FastAPI(
    title="ClickHouse MCP Server",
    description="A Model Context Protocol server for ClickHouse databases",
    version="1.0.0",
    debug=True,  # Enable FastAPI debug mode
)


# Create a custom HTTP client with auth header
class AuthClient(httpx.AsyncClient):
    def __init__(self, auth_token: str, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.headers.update({"Authorization": f"Bearer {auth_token}"})


# Create FastAPI-MCP instance
mcp = FastApiMCP(
    app,
    name="mcp-clickhouse-fastapi",
    description="ClickHouse database access via MCP",
    base_url="http://localhost/mcp",
    describe_all_responses=True,
    describe_full_response_schema=True,
)


# Dependency to get auth client for each request
async def get_auth_client(request: Request) -> AuthClient:
    auth_header = request.headers.get("authorization")
    if not auth_header:
        raise HTTPException(status_code=401, detail="Missing Authorization header")

    try:
        token = auth_header.split(" ")[1]
        return AuthClient(auth_token=token)
    except IndexError:
        raise HTTPException(status_code=401, detail="Invalid Authorization header format")


# Add middleware to log requests
@app.middleware("http")
async def log_requests(request, call_next):
    logger.debug(f"Incoming request: {request.method} {request.url}")
    logger.debug(f"Headers: {request.headers}")

    # Create a new auth client for this request
    request.state.auth_client = await get_auth_client(request)

    # Set the client in MCP for this request
    mcp._http_client = request.state.auth_client

    response = await call_next(request)
    logger.debug(f"Response status: {response.status_code}")
    return response

It's a tricky solution, although it'd be great to be handled by FastAPI MCP out of the box.

@YoshitakaOyama
Copy link

@jsulopzs
Thank you for implementing the code!
I was able to make it work by extensively implementing the httpx client in the middleware as in your code.

Thank you very much!

@davidmezzetti
Copy link

davidmezzetti commented Apr 21, 2025

I agree. This would be a good one to have a built-in way to handle this.

Seems related to #10?

@shira-ayal
Copy link
Collaborator

Hi all!
Check out the latest version, including this example and the docs on how to add auth headers to your MCP.

@jsulopzs @YoshitakaOyama @davidmezzetti

@davidmezzetti
Copy link

Awesome, great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants