Guide
Requirements
Section titled “Requirements”| Package | Required | Purpose |
|---|---|---|
lexigram | Yes | Core framework |
lexigram-contracts | Yes | Protocol definitions |
lexigram-ai-agents | Optional | Agent system bridging |
lexigram-ai-skills | 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 Lexigram 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 lexigram.ai.mcp import MCPController, tool, MCPModulefrom lexigram.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 lexigram.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 lexigram.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 lexigram-ai-skills
Section titled “Bridge to lexigram-ai-skills”When lexigram-ai-skills 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