Requirements
Section titled “Requirements”| Package | Required | Purpose |
|---|---|---|
quadkit | Yes | Core framework |
quadkit-contracts | Yes | Protocol definitions |
quadkit-ai-agents | Optional | Agent system bridging |
an AI skills extension | Optional | Skills-to-MCP bridging |
MCP servers let AI agents — like Claude Desktop or custom LLM applications — interact with your application through tools, resources, and prompts.
The package wraps the Model Context Protocol as a first-class Quadkit citizen: handlers, transports, and connectors are wired through the DI container with the same provider/module lifecycle as any other extension.
Core Concepts
Section titled “Core Concepts”Server vs Client
Section titled “Server vs Client”| Role | Class | Purpose |
|---|---|---|
| Server | MCPServer | Exposes tools/resources/prompts to AI clients. JSON-RPC message router. |
| Client | MCPClient | Connects to external MCP servers (stdio or SSE) and calls their tools. |
Tools, Resources, Prompts
Section titled “Tools, Resources, Prompts”An MCP server exposes three capability types:
- Tools — callable functions the AI can invoke (
tools/list,tools/call). - Resources — data the AI can read (
resources/list,resources/read). - Prompts — template-driven messages (
prompts/list,prompts/get).
Handlers
Section titled “Handlers”Handlers implement the routing for each capability:
| Handler | Registers | Dispatches to |
|---|---|---|
ToolHandler | @tool-decorated methods, MCPController subclasses, connectors | MCPToolProviderProtocol |
ResourceHandler | @resource-decorated methods, connectors | MCPResourceProviderProtocol |
PromptHandler | @prompt-decorated methods | MCPPromptProviderProtocol |
Transports
Section titled “Transports”| Transport | Direction | I/O |
|---|---|---|
StdioTransport | Server-side | stdin/stdout (local desktop tools) |
SSETransport | Server-side | HTTP + Server-Sent Events |
StdioClientTransport | Client-side | stdin/stdout subprocess |
SSEClientTransport | Client-side | HTTP POST + SSE |
Typical Usage
Section titled “Typical Usage”Exposing Tools via MCPController
Section titled “Exposing Tools via MCPController”from quadkit.ai.mcp import MCPController, tool, MCPModulefrom quadkit.contracts.data.vector.protocols import VectorStoreProtocol
class SearchController(MCPController): def __init__(self, vector_store: VectorStoreProtocol) -> None: self._store = vector_store
@tool("search_docs", description="Search documents by query") async def search_docs(self, query: str, limit: int = 10) -> list[dict]: result = await self._store.similarity_search(query, k=limit) return result.unwrap_or([])
# Wiringmodule = MCPModule.configure(controllers=[SearchController])Auto-Exposing Existing Services
Section titled “Auto-Exposing Existing Services”module = MCPModule.from_services( services=[UserService, AnalyticsService], include_methods=["search", "get_*"],)Service methods matching the glob are registered as MCP tools automatically.
Connecting to External MCP Servers (Client)
Section titled “Connecting to External MCP Servers (Client)”from quadkit.ai.mcp.client import MCPClientModule, MCPConnection
module = MCPClientModule.configure( connections=[ MCPConnection.stdio(["uvx", "mcp-server-git"], name="git"), MCPConnection.sse("http://localhost:9000/mcp", name="local"), ],)Inject MCPClientRegistry for named access or MCPClient for the primary connection.
Common Patterns
Section titled “Common Patterns”Exposing Connectors Conditionally
Section titled “Exposing Connectors Conditionally”ai_mcp: connectors: filesystem: root_dir: "/workspace" # enables FilesystemConnector read_only: true web_fetch: enabled: true github: token: "${GITHUB_TOKEN}" # enables GitHubConnectorConnectors are enabled by supplying the required config keys — absent keys disable the connector.
Custom Tool Provider
Section titled “Custom Tool Provider”from quadkit.contracts.mcp.protocols import MCPToolProviderProtocol
class MyToolProvider: async def list_tools(self) -> list[dict[str, Any]]: return [{"name": "hello", "description": "Say hello", "inputSchema": {}}]
async def call_tool(self, name: str, arguments: dict[str, Any]) -> dict[str, Any]: return {"content": [{"type": "text", "text": "Hello!"}]}Register it in a custom provider’s boot() against MCPToolProviderProtocol.
Bridge to an AI skills extension
Section titled “Bridge to an AI skills extension”When an AI skills extension is installed and its provider is registered, SkillToolAdapter is automatically created — all skills become MCP tools.
Best Practices
Section titled “Best Practices”- ✅ Use
MCPModule.from_services()for quick prototyping,MCPControllerfor production. - ✅ Set
read_only: trueon connectors that should never mutate state. - ✅ Set
enable_streaming: Falsein tests to simplify assertions. - ❌ Don’t import
MCPServerfrom the server module directly — resolve it from the container. - ❌ Don’t expose database write connectors (
sql.read_only: false) to untrusted AI clients.
Next Steps
Section titled “Next Steps”- How-Tos — specific task recipes
- Configuration — every config key
- Architecture — internal design and extension points