60e0ffc959
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
127 lines
4.8 KiB
Python
127 lines
4.8 KiB
Python
import json
|
|
import os
|
|
|
|
import pytest
|
|
from mcp import MCPError
|
|
from mcp_types import Resource, TextContent, Tool
|
|
|
|
from fastmcp import Client
|
|
from fastmcp.client import StreamableHttpTransport
|
|
from fastmcp.client.auth.bearer import BearerAuth
|
|
|
|
GITHUB_REMOTE_MCP_URL = "https://api.githubcopilot.com/mcp/"
|
|
|
|
HEADER_AUTHORIZATION = "Authorization"
|
|
FASTMCP_GITHUB_TOKEN = os.getenv("FASTMCP_GITHUB_TOKEN")
|
|
|
|
|
|
# Skip tests if no GitHub token is available
|
|
pytestmark = pytest.mark.xfail(
|
|
not FASTMCP_GITHUB_TOKEN,
|
|
reason="The FASTMCP_GITHUB_TOKEN environment variable is not set or empty",
|
|
)
|
|
|
|
|
|
@pytest.fixture(name="streamable_http_client")
|
|
def fixture_streamable_http_client() -> Client[StreamableHttpTransport]:
|
|
assert FASTMCP_GITHUB_TOKEN is not None
|
|
|
|
return Client(
|
|
StreamableHttpTransport(
|
|
url=GITHUB_REMOTE_MCP_URL,
|
|
auth=BearerAuth(FASTMCP_GITHUB_TOKEN),
|
|
)
|
|
)
|
|
|
|
|
|
class TestGithubMCPRemote:
|
|
async def test_connect_disconnect(
|
|
self,
|
|
streamable_http_client: Client[StreamableHttpTransport],
|
|
):
|
|
async with streamable_http_client:
|
|
assert streamable_http_client.is_connected() is True
|
|
await streamable_http_client._disconnect() # pylint: disable=W0212 (protected-access)
|
|
assert streamable_http_client.is_connected() is False
|
|
|
|
async def test_ping(self, streamable_http_client: Client[StreamableHttpTransport]):
|
|
"""Test pinging the server."""
|
|
async with streamable_http_client:
|
|
assert streamable_http_client.is_connected() is True
|
|
result = await streamable_http_client.ping()
|
|
assert result is True
|
|
|
|
async def test_list_tools(
|
|
self, streamable_http_client: Client[StreamableHttpTransport]
|
|
):
|
|
"""Test listing the MCP tools"""
|
|
async with streamable_http_client:
|
|
assert streamable_http_client.is_connected()
|
|
tools = await streamable_http_client.list_tools()
|
|
assert isinstance(tools, list)
|
|
assert len(tools) > 0 # Ensure the tools list is non-empty
|
|
for tool in tools:
|
|
assert isinstance(tool, Tool)
|
|
assert len(tool.name) > 0
|
|
assert tool.description is not None and len(tool.description) > 0
|
|
assert isinstance(tool.input_schema, dict)
|
|
assert len(tool.input_schema) > 0
|
|
|
|
async def test_list_resources(
|
|
self, streamable_http_client: Client[StreamableHttpTransport]
|
|
):
|
|
"""Test listing the MCP resources"""
|
|
async with streamable_http_client:
|
|
assert streamable_http_client.is_connected()
|
|
resources = await streamable_http_client.list_resources()
|
|
assert isinstance(resources, list)
|
|
for resource in resources:
|
|
assert isinstance(resource, Resource)
|
|
assert resource.name
|
|
assert str(resource.uri)
|
|
|
|
async def test_list_prompts(
|
|
self, streamable_http_client: Client[StreamableHttpTransport]
|
|
):
|
|
"""Test listing the MCP prompts"""
|
|
async with streamable_http_client:
|
|
assert streamable_http_client.is_connected()
|
|
prompts = await streamable_http_client.list_prompts()
|
|
# there is at least one prompt (as of July 2025)
|
|
assert len(prompts) >= 1
|
|
|
|
async def test_call_tool_ko(
|
|
self, streamable_http_client: Client[StreamableHttpTransport]
|
|
):
|
|
"""Test calling a non-existing tool"""
|
|
async with streamable_http_client:
|
|
assert streamable_http_client.is_connected()
|
|
with pytest.raises(MCPError, match=r"unknown tool|tool not found"):
|
|
await streamable_http_client.call_tool("foo")
|
|
|
|
async def test_call_tool_list_commits(
|
|
self,
|
|
streamable_http_client: Client[StreamableHttpTransport],
|
|
):
|
|
"""Test calling a list_commit tool"""
|
|
async with streamable_http_client:
|
|
assert streamable_http_client.is_connected()
|
|
result = await streamable_http_client.call_tool(
|
|
"list_commits", {"owner": "prefecthq", "repo": "fastmcp"}
|
|
)
|
|
|
|
# at this time, the github server does not support structured content
|
|
assert result.structured_content is None
|
|
assert isinstance(result.content, list)
|
|
assert len(result.content) == 1
|
|
assert isinstance(result.content[0], TextContent)
|
|
commits = json.loads(result.content[0].text)
|
|
for commit in commits:
|
|
assert isinstance(commit, dict)
|
|
assert "sha" in commit
|
|
assert "commit" in commit
|
|
assert "author" in commit["commit"]
|
|
assert len(commit["commit"]["author"]["date"]) > 0
|
|
assert len(commit["commit"]["author"]["name"]) > 0
|
|
assert len(commit["commit"]["author"]["email"]) > 0
|