Skip to content

Updated Few docstrings and Ran ruff checks #200

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ First off, thank you for considering contributing to FastAPI-MCP!

```bash
git clone https://github.com/YOUR-USERNAME/fastapi_mcp.git
cd fastapi-mcp
cd fastapi_mcp

# Add the upstream remote
git remote add upstream https://github.com/tadata-org/fastapi_mcp.git
Expand Down
4 changes: 2 additions & 2 deletions examples/01_basic_usage_example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from examples.shared.apps.items import app # The FastAPI app
from examples.shared.apps.items import app # The FastAPI app
from examples.shared.setup import setup_logging

from fastapi_mcp import FastApiMCP
Expand All @@ -15,4 +15,4 @@
if __name__ == "__main__":
import uvicorn

uvicorn.run(app, host="0.0.0.0", port=8000)
uvicorn.run(app, host="0.0.0.0", port=8000)
6 changes: 3 additions & 3 deletions examples/02_full_schema_description_example.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

"""
This example shows how to describe the full response schema instead of just a response example.
"""
from examples.shared.apps.items import app # The FastAPI app

from examples.shared.apps.items import app # The FastAPI app
from examples.shared.setup import setup_logging

from fastapi_mcp import FastApiMCP
Expand All @@ -22,5 +22,5 @@

if __name__ == "__main__":
import uvicorn

uvicorn.run(app, host="0.0.0.0", port=8000)
5 changes: 3 additions & 2 deletions examples/03_custom_exposed_endpoints_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
- You can combine operation filtering with tag filtering (e.g., use `include_operations` with `include_tags`)
- When combining filters, a greedy approach will be taken. Endpoints matching either criteria will be included
"""
from examples.shared.apps.items import app # The FastAPI app

from examples.shared.apps.items import app # The FastAPI app
from examples.shared.setup import setup_logging

from fastapi_mcp import FastApiMCP
Expand All @@ -24,7 +25,7 @@

# Filter by excluding specific operation IDs
exclude_operations_mcp = FastApiMCP(
app,
app,
name="Item API MCP - Excluded Operations",
exclude_operations=["create_item", "update_item", "delete_item"],
)
Expand Down
3 changes: 2 additions & 1 deletion examples/04_separate_server_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This example shows how to run the MCP server and the FastAPI app separately.
You can create an MCP server from one FastAPI app, and mount it to a different app.
"""

from fastapi import FastAPI

from examples.shared.apps.items import app
Expand Down Expand Up @@ -30,4 +31,4 @@
if __name__ == "__main__":
import uvicorn

uvicorn.run(mcp_app, host="0.0.0.0", port=8000)
uvicorn.run(mcp_app, host="0.0.0.0", port=8000)
9 changes: 5 additions & 4 deletions examples/05_reregister_tools_example.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"""
This example shows how to re-register tools if you add endpoints after the MCP server was created.
"""
from examples.shared.apps.items import app # The FastAPI app

from examples.shared.apps.items import app # The FastAPI app
from examples.shared.setup import setup_logging

from fastapi_mcp import FastApiMCP

setup_logging()

mcp = FastApiMCP(app) # Add MCP server to the FastAPI app
mcp.mount() # MCP server
mcp = FastApiMCP(app) # Add MCP server to the FastAPI app
mcp.mount() # MCP server


# This endpoint will not be registered as a tool, since it was added after the MCP instance was created
Expand All @@ -24,5 +25,5 @@ async def new_endpoint():

if __name__ == "__main__":
import uvicorn

uvicorn.run(app, host="0.0.0.0", port=8000)
7 changes: 4 additions & 3 deletions examples/06_custom_mcp_router_example.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"""
This example shows how to mount the MCP server to a specific APIRouter, giving a custom mount path.
"""
from examples.shared.apps.items import app # The FastAPI app

from examples.shared.apps.items import app # The FastAPI app
from examples.shared.setup import setup_logging

from fastapi import APIRouter
from fastapi_mcp import FastApiMCP

setup_logging()

other_router = APIRouter(prefix="/other/route")
other_router = APIRouter(prefix="/other/route")
app.include_router(other_router)

mcp = FastApiMCP(app)
Expand All @@ -21,5 +22,5 @@

if __name__ == "__main__":
import uvicorn

uvicorn.run(app, host="0.0.0.0", port=8000)
10 changes: 4 additions & 6 deletions examples/07_configure_http_timeout_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
This example shows how to configure the HTTP client timeout for the MCP server.
In case you have API endpoints that take longer than 5 seconds to respond, you can increase the timeout.
"""
from examples.shared.apps.items import app # The FastAPI app

from examples.shared.apps.items import app # The FastAPI app
from examples.shared.setup import setup_logging

import httpx
Expand All @@ -12,14 +13,11 @@
setup_logging()


mcp = FastApiMCP(
app,
http_client=httpx.AsyncClient(timeout=20)
)
mcp = FastApiMCP(app, http_client=httpx.AsyncClient(timeout=20))
mcp.mount()


if __name__ == "__main__":
import uvicorn

uvicorn.run(app, host="0.0.0.0", port=8000)
11 changes: 7 additions & 4 deletions examples/08_auth_example_token_passthrough.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
}
```
"""
from examples.shared.apps.items import app # The FastAPI app

from examples.shared.apps.items import app # The FastAPI app
from examples.shared.setup import setup_logging

from fastapi import Depends
Expand All @@ -34,11 +35,13 @@
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer()


# Create a private endpoint
@app.get("/private")
async def private(token = Depends(token_auth_scheme)):
async def private(token=Depends(token_auth_scheme)):
return token.credentials


# Create the MCP server with the token auth scheme
mcp = FastApiMCP(
app,
Expand All @@ -54,5 +57,5 @@ async def private(token = Depends(token_auth_scheme)):

if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

uvicorn.run(app, host="0.0.0.0", port=8000)
5 changes: 4 additions & 1 deletion fastapi_mcp/openapi/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ def convert_openapi_to_mcp_tools(
if display_schema.get("type") == "array" and "items" in display_schema:
items_schema = display_schema["items"]

response_info += "\n\n**Output Schema:** Array of items with the following structure:\n```json\n"
response_info += (
"\n\n**Output Schema:** Array of items with the following "
"structure:\n```json\n"
)
response_info += json.dumps(items_schema, indent=2)
response_info += "\n```"
elif "properties" in display_schema:
Expand Down
9 changes: 7 additions & 2 deletions fastapi_mcp/openapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ def get_single_param_type_from_schema(param_schema: Dict[str, Any]) -> str:
"""
Get the type of a parameter from the schema.
If the schema is a union type, return the first type.

Args:
param_schema (Dict[str, Any]): Schema definition.
Returns:
str: The type of a parameter.
"""
if "anyOf" in param_schema:
types = {schema.get("type") for schema in param_schema["anyOf"] if schema.get("type")}
Expand All @@ -25,7 +30,7 @@ def resolve_schema_references(schema_part: Dict[str, Any], reference_schema: Dic
reference_schema: The complete schema used to resolve references from

Returns:
The schema with references resolved
dict: The schema with references resolved
"""
# Make a copy to avoid modifying the input schema
schema_part = schema_part.copy()
Expand Down Expand Up @@ -65,7 +70,7 @@ def clean_schema_for_display(schema: Dict[str, Any]) -> Dict[str, Any]:
schema: The schema to clean

Returns:
The cleaned schema
dict: The cleaned schema
"""
# Make a copy to avoid modifying the input schema
schema = schema.copy()
Expand Down
11 changes: 7 additions & 4 deletions fastapi_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ async def _execute_api_tool(
logger.debug(f"Making {method.upper()} request to {path}")
response = await self._request(client, method, path, query, headers, body)

# TODO: Better typing for the AsyncClientProtocol. It should return a ResponseProtocol that has a json() method that returns a dict/list/etc.
# TODO: Better typing for the AsyncClientProtocol. It should return a ResponseProtocol that has a json()
# method that returns a dict/list/etc.
try:
result = response.json()
result_text = json.dumps(result, indent=2, ensure_ascii=False)
Expand All @@ -439,8 +440,10 @@ async def _execute_api_tool(
else:
result_text = response.content

# If not raising an exception, the MCP server will return the result as a regular text response, without marking it as an error.
# TODO: Use a raise_for_status() method on the response (it needs to also be implemented in the AsyncClientProtocol)
# If not raising an exception, the MCP server will return the result as a regular text response,
# without marking it as an error.
# TODO: Use a raise_for_status() method on the response (it needs to also
# be implemented in the AsyncClientProtocol)
if 400 <= response.status_code < 600:
raise Exception(
f"Error calling {tool_name}. Status code: {response.status_code}. Response: {response.text}"
Expand Down Expand Up @@ -486,7 +489,7 @@ def _filter_tools(self, tools: List[types.Tool], openapi_schema: Dict[str, Any])
openapi_schema: The OpenAPI schema

Returns:
Filtered list of tools
list: Filtered list of tools
"""
if (
self._include_operations is None
Expand Down
Loading