Sahaj.blogs
30 Sept 2026 · StudyPhase 15 · Agentic AI

Agentic AI · Model Context Protocol (MCP)

MCP standardises how applications expose tools, resources and prompts to LLM clients; an MCP server built with the official Python SDK and queried from an in-process client.

Every agent framework had its own way to define tools, so each integration had to be written again for each framework. The Model Context Protocol (MCP), introduced by Anthropic in November 2024 as an open standard, defines one protocol between:

  • clients: the AI application (an assistant, an IDE, an agent)
  • servers: programs that expose capabilities

A server offers three kinds of things:

  • tools: functions the model can call (with JSON-schema inputs)
  • resources: data the client can read (files, records), addressed by URI
  • prompts: reusable prompt templates

Transports include stdio (a local subprocess) and HTTP.

I built a tiny server for my blog notes with the official Python SDK. The installed version, 2.3, renamed FastMCP to MCPServer, and the import error pointed me to the migration guide. Then I connected to it in-process with the SDK’s Client, which is what an AI app would do over stdio or HTTP.

import asyncio
from mcp import Client
from mcp.server.mcpserver import MCPServer

notes = {"python": "Phase 1 (Aug-Oct 2023)", "langchain": "Phase 13 (Apr-May 2026)", "agentic": "Phase 15 (Aug 2026-)"}
server = MCPServer("sahaj-notes")

@server.tool()
def find_phase(topic: str) -> str:
    """Return which learning-path phase covered a topic."""
    return notes.get(topic.lower(), "not on my learning path")

@server.tool()
def count_phases() -> int:
    """Return the number of phases in the learning path."""
    return 15

@server.resource("notes://learning-path")
def learning_path() -> str:
    return "; ".join(f"{k}: {v}" for k, v in notes.items())

async def main():
    async with Client(server) as client:
        tools = await client.list_tools()
        for t in tools.tools:
            print(f"tool {t.name}: {t.description} | input schema: {t.input_schema['properties']}")
        r = await client.call_tool("find_phase", {"topic": "LangChain"})
        print("call find_phase ->", r.content[0].text, "| error:", r.is_error)
        print("call count_phases ->", (await client.call_tool("count_phases", {})).content[0].text)
        res = await client.list_resources()
        print("resources:", [str(x.uri) for x in res.resources])
        print("read ->", (await client.read_resource("notes://learning-path")).contents[0].text)

asyncio.run(main())

Output:

tool find_phase: Return which learning-path phase covered a topic. | input schema: {'topic': {'title': 'Topic', 'type': 'string'}}
tool count_phases: Return the number of phases in the learning path. | input schema: {}
call find_phase -> Phase 13 (Apr-May 2026) | error: False
call count_phases -> 15
resources: ['notes://learning-path']
read -> python: Phase 1 (Aug-Oct 2023); langchain: Phase 13 (Apr-May 2026); agentic: Phase 15 (Aug 2026-)

#agents#mcp#tools

Sources

  1. Model Context Protocol: Introduction — Model Context Protocol
  2. Model Context Protocol specification — Model Context Protocol
  3. MCP Python SDK (modelcontextprotocol/python-sdk) — GitHub
  4. Anthropic: Introducing the Model Context Protocol — Anthropic