added specs
This commit is contained in:
parent
9681ec94e6
commit
21a38ebe74
1 changed files with 3532 additions and 60 deletions
|
|
@ -3,6 +3,357 @@ title: "Python Type Hints"
|
|||
description: "Python type system documentation"
|
||||
---
|
||||
|
||||
# Python Type Hints
|
||||
## Core Types
|
||||
|
||||
Python type system documentation
|
||||
### 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
|
||||
})
|
||||
```
|
||||
Loading…
Reference in a new issue