359 lines
No EOL
8.7 KiB
Text
359 lines
No EOL
8.7 KiB
Text
---
|
|
title: "Python type hints"
|
|
description: "Python type system documentation"
|
|
---
|
|
|
|
## Core types
|
|
|
|
### Resource types
|
|
|
|
```python
|
|
from typing import TypedDict, Optional, Literal, Union, List
|
|
|
|
class Resource(TypedDict):
|
|
"""Represents a resource that can be accessed through MCP."""
|
|
uri: str
|
|
name: str
|
|
description: Optional[str]
|
|
mimeType: Optional[str]
|
|
|
|
class ResourceTemplate(TypedDict):
|
|
"""Template for constructing resource URIs."""
|
|
uriTemplate: str
|
|
name: str
|
|
description: Optional[str]
|
|
mimeType: Optional[str]
|
|
|
|
class ResourceContents(TypedDict):
|
|
"""Contents of a specific resource."""
|
|
uri: str
|
|
mimeType: Optional[str]
|
|
|
|
class TextResourceContents(ResourceContents):
|
|
"""Resource contents in text format."""
|
|
text: str
|
|
|
|
class BlobResourceContents(ResourceContents):
|
|
"""Resource contents in binary format."""
|
|
blob: bytes # Base64 encoded
|
|
```
|
|
|
|
### Message types
|
|
|
|
```python
|
|
class TextContent(TypedDict):
|
|
"""Text content in a message."""
|
|
type: Literal["text"]
|
|
text: str
|
|
|
|
class ImageContent(TypedDict):
|
|
"""Image content in a message."""
|
|
type: Literal["image"]
|
|
data: str # Base64 encoded
|
|
mimeType: str
|
|
|
|
MessageContent = Union[TextContent, ImageContent]
|
|
|
|
class Message(TypedDict):
|
|
"""A message in an LLM conversation."""
|
|
role: Literal["user", "assistant"]
|
|
content: MessageContent
|
|
```
|
|
|
|
### Tool types
|
|
|
|
```python
|
|
class ToolParameter(TypedDict):
|
|
"""Parameter definition for a tool."""
|
|
type: str
|
|
description: Optional[str]
|
|
required: Optional[bool]
|
|
|
|
class ToolSchema(TypedDict):
|
|
"""JSON Schema for tool parameters."""
|
|
type: Literal["object"]
|
|
properties: dict[str, ToolParameter]
|
|
required: Optional[List[str]]
|
|
|
|
class Tool(TypedDict):
|
|
"""Definition of a tool that can be called through MCP."""
|
|
name: str
|
|
description: str
|
|
inputSchema: ToolSchema
|
|
```
|
|
|
|
### Prompt types
|
|
|
|
```python
|
|
class PromptArgument(TypedDict):
|
|
"""Argument definition for a prompt template."""
|
|
name: str
|
|
description: Optional[str]
|
|
required: Optional[bool]
|
|
|
|
class Prompt(TypedDict):
|
|
"""A prompt template that can be used through MCP."""
|
|
name: str
|
|
description: Optional[str]
|
|
arguments: Optional[List[PromptArgument]]
|
|
|
|
class PromptResponse(TypedDict):
|
|
"""Response to a prompt request."""
|
|
description: Optional[str]
|
|
messages: List[Message]
|
|
```
|
|
|
|
### Progress types
|
|
|
|
```python
|
|
class Progress(TypedDict):
|
|
"""Progress information for long-running operations."""
|
|
progress: int
|
|
total: Optional[int]
|
|
```
|
|
|
|
### Logging types
|
|
|
|
```python
|
|
LogLevel = Literal["debug", "info", "warning", "error"]
|
|
|
|
class LogMessage(TypedDict):
|
|
"""A log message sent through MCP."""
|
|
level: LogLevel
|
|
logger: Optional[str]
|
|
data: Any # JSON-serializable value
|
|
```
|
|
|
|
## Request/Response types
|
|
|
|
### Resource requests
|
|
|
|
```python
|
|
class ListResourcesRequest(TypedDict):
|
|
"""Request to list available resources."""
|
|
cursor: Optional[str]
|
|
|
|
class ListResourcesResponse(TypedDict):
|
|
"""Response containing available resources."""
|
|
resources: List[Resource]
|
|
nextCursor: Optional[str]
|
|
|
|
class ReadResourceRequest(TypedDict):
|
|
"""Request to read a specific resource."""
|
|
uri: str
|
|
|
|
class ReadResourceResponse(TypedDict):
|
|
"""Response containing resource contents."""
|
|
contents: List[Union[TextResourceContents, BlobResourceContents]]
|
|
|
|
class SubscribeRequest(TypedDict):
|
|
"""Request to subscribe to resource updates."""
|
|
uri: str
|
|
|
|
class UnsubscribeRequest(TypedDict):
|
|
"""Request to unsubscribe from resource updates."""
|
|
uri: str
|
|
```
|
|
|
|
### Tool requests
|
|
|
|
```python
|
|
class ListToolsRequest(TypedDict):
|
|
"""Request to list available tools."""
|
|
cursor: Optional[str]
|
|
|
|
class ListToolsResponse(TypedDict):
|
|
"""Response containing available tools."""
|
|
tools: List[Tool]
|
|
nextCursor: Optional[str]
|
|
|
|
class CallToolRequest(TypedDict):
|
|
"""Request to call a specific tool."""
|
|
name: str
|
|
arguments: Optional[dict]
|
|
|
|
class CallToolResponse(TypedDict):
|
|
"""Response from a tool call."""
|
|
toolResult: Any # JSON-serializable value
|
|
```
|
|
|
|
### Prompt requests
|
|
|
|
```python
|
|
class ListPromptsRequest(TypedDict):
|
|
"""Request to list available prompts."""
|
|
cursor: Optional[str]
|
|
|
|
class ListPromptsResponse(TypedDict):
|
|
"""Response containing available prompts."""
|
|
prompts: List[Prompt]
|
|
nextCursor: Optional[str]
|
|
|
|
class GetPromptRequest(TypedDict):
|
|
"""Request to get a specific prompt."""
|
|
name: str
|
|
arguments: Optional[dict[str, str]]
|
|
```
|
|
|
|
## Protocol types
|
|
|
|
### Implementation Info
|
|
|
|
```python
|
|
class Implementation(TypedDict):
|
|
"""Information about an MCP implementation."""
|
|
name: str
|
|
version: str
|
|
```
|
|
|
|
### Capabilities
|
|
|
|
```python
|
|
class ResourceCapabilities(TypedDict):
|
|
"""Capabilities related to resources."""
|
|
subscribe: Optional[bool]
|
|
listChanged: Optional[bool]
|
|
|
|
class PromptCapabilities(TypedDict):
|
|
"""Capabilities related to prompts."""
|
|
listChanged: Optional[bool]
|
|
|
|
class ToolCapabilities(TypedDict):
|
|
"""Capabilities related to tools."""
|
|
listChanged: Optional[bool]
|
|
|
|
class ServerCapabilities(TypedDict):
|
|
"""Complete set of server capabilities."""
|
|
experimental: Optional[dict]
|
|
logging: Optional[dict]
|
|
prompts: Optional[PromptCapabilities]
|
|
resources: Optional[ResourceCapabilities]
|
|
tools: Optional[ToolCapabilities]
|
|
```
|
|
|
|
## Transport types
|
|
|
|
### Stream types
|
|
|
|
```python
|
|
class ReadStream(Protocol):
|
|
"""Protocol for reading from a transport."""
|
|
async def read(self) -> bytes: ...
|
|
|
|
class WriteStream(Protocol):
|
|
"""Protocol for writing to a transport."""
|
|
async def write(self, data: bytes) -> None: ...
|
|
```
|
|
|
|
### Session types
|
|
|
|
```python
|
|
class ServerSession(Protocol):
|
|
"""Protocol for server-side session operations."""
|
|
async def send_resource_updated(self, uri: str) -> None: ...
|
|
async def send_progress_notification(
|
|
self, token: str, progress: int, total: Optional[int] = None
|
|
) -> None: ...
|
|
async def send_log_message(
|
|
self, level: LogLevel, data: Any, logger: Optional[str] = None
|
|
) -> None: ...
|
|
```
|
|
|
|
## Usage examples
|
|
|
|
### Type usage in handlers
|
|
|
|
```python
|
|
from mcp_python.server import Server
|
|
from mcp_python.types import Resource, Tool, PromptResponse, Message
|
|
|
|
server = Server("example")
|
|
|
|
@server.list_resources()
|
|
async def list_resources() -> List[Resource]:
|
|
return [
|
|
{
|
|
"uri": "example://test",
|
|
"name": "Test Resource",
|
|
"description": "A test resource",
|
|
"mimeType": "text/plain"
|
|
}
|
|
]
|
|
|
|
@server.list_tools()
|
|
async def list_tools() -> List[Tool]:
|
|
return [
|
|
{
|
|
"name": "test-tool",
|
|
"description": "A test tool",
|
|
"inputSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"param": {
|
|
"type": "string",
|
|
"description": "A parameter"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
|
|
@server.get_prompt()
|
|
async def get_prompt(name: str, arguments: dict) -> PromptResponse:
|
|
return {
|
|
"description": "A test prompt",
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"content": {
|
|
"type": "text",
|
|
"text": f"Test prompt with args: {arguments}"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Type checking
|
|
|
|
```python
|
|
from typing import TypeGuard
|
|
|
|
def is_text_content(content: MessageContent) -> TypeGuard[TextContent]:
|
|
"""Type guard for text content."""
|
|
return content["type"] == "text"
|
|
|
|
def process_message(message: Message) -> str:
|
|
content = message["content"]
|
|
if is_text_content(content):
|
|
return content["text"]
|
|
return f"Image message with type: {content['mimeType']}"
|
|
```
|
|
|
|
## Additional notes
|
|
|
|
- All types are compatible with standard Python type checkers (mypy, pyright)
|
|
- TypedDict is used extensively to ensure proper structure of JSON-like objects
|
|
- Literal types are used to restrict string values to specific options
|
|
- Optional fields use the Optional type hint to indicate nullable values
|
|
- Protocol classes define interface contracts for pluggable components
|
|
|
|
For runtime type checking, you can use the following pattern:
|
|
|
|
```python
|
|
from typing import cast
|
|
from typing_extensions import assert_type
|
|
|
|
def validate_resource(data: dict) -> Resource:
|
|
"""Validate and convert a dict to a Resource type."""
|
|
required_fields = {"uri", "name"}
|
|
if not all(field in data for field in required_fields):
|
|
raise ValueError("Missing required fields")
|
|
|
|
return cast(Resource, {
|
|
"uri": str(data["uri"]),
|
|
"name": str(data["name"]),
|
|
"description": str(data.get("description")) if "description" in data else None,
|
|
"mimeType": str(data.get("mimeType")) if "mimeType" in data else None
|
|
})
|
|
``` |