Skip to main content
Glama
binodrajpandey

MCP Server Example

README.md
# MCP Server Example

A simple MCP (Model Context Protocol) server for learning the core primitives: **Tools**, **Resources**, and **Prompts**.

## Setup

### Prerequisites

- Python 3.10+
- [uv](https://docs.astral.sh/uv/getting-started/installation/)

### Install

```bash
uv sync
```

## Test

### Option 1 — MCP Inspector (recommended)

```bash
uv run mcp dev server.py
```

Opens a browser UI at `http://localhost:6274`. From there you can:
- **Tools tab**: call `save_note`, `delete_note` with custom inputs
- **Resources tab**: read `notes://list` or `notes://{name}`
- **Prompts tab**: run `summarize_notes` or `brainstorm` with arguments

### Option 2 — CLI with `mcp` client

List all available tools:

```bash
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | uv run python server.py
```

## Connect to Claude Code (CLI)

Add the server to your Claude Code session:

```bash
claude mcp add learning-mcp -- uv run --directory /Users/binod/projects/mcp-example python server.py
```

Verify it's connected:

```bash
claude mcp list
```

Once added, Claude Code can call your tools directly in the chat — just ask it to, e.g. _"save a note called 'ideas'"_.

## Connect to Claude Desktop

Add this to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "learning-mcp": {
      "command": "uv",
      "args": [
        "run",
        "--directory", "/Users/binod/projects/mcp-example",
        "python", "server.py"
      ]
    }
  }
}
```

Then restart Claude Desktop.

## Use programmatically (Python)

Use the `mcp` library to call tools, read resources, and fetch prompts from your own code:

```python
from mcp import ClientSession
from mcp.client.stdio import stdio_client, StdioServerParameters
import asyncio

async def main():
    server = StdioServerParameters(
        command="uv", args=["run", "python", "server.py"]
    )
    async with stdio_client(server) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Read a resource
            notes = await session.read_resource("notes://list")
            print(notes)

            # Get a prompt
            prompt = await session.get_prompt("brainstorm", {"topic": "side projects"})
            print(prompt)

asyncio.run(main())
```

To let **Claude (via Anthropic API)** call your tools, add `anthropic[mcp]` to your dependencies and convert the tools:

```python
from anthropic.lib.tools.mcp import async_mcp_tool
import anthropic

client = anthropic.AsyncAnthropic()
tools = [async_mcp_tool(t, session) for t in (await session.list_tools()).tools]

runner = client.beta.messages.tool_runner(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Save a note called ideas"}],
    tools=tools,
)
async for message in runner:
    for block in message.content:
        if hasattr(block, "text"):
            print(block.text)
```

## What's inside

| File | Description |
|------|-------------|
| `server.py` | MCP server with tools, resources, and prompts |
| `pyproject.toml` | Project dependencies |

### Tools (Claude can call these)

| Tool | Description |
|------|-------------|
| `save_note(name, content)` | Save a note |
| `delete_note(name)` | Delete a note |

### Resources (Claude can read these)

| URI | Description |
|-----|-------------|
| `notes://list` | List all saved notes |
| `notes://{name}` | Read a specific note |

### Prompts (reusable templates)

| Prompt | Description |
|--------|-------------|
| `summarize_notes` | Summarize all saved notes |
| `brainstorm(topic)` | Brainstorm ideas on a topic |

TDQS

C2.6/5.0

Scored across 4 tools

Disambiguation2/5

The tools fall into two unrelated domains (arithmetic and note management) with no overlap within each domain, but the set as a whole is confusing because add/multiply and delete_note/save_note serve completely different purposes. An agent might struggle to understand why these tools are grouped together, though individual tools are distinct.

Naming Consistency2/5

Naming is inconsistent across the set: add and multiply use simple verbs without objects, while delete_note and save_note follow a verb_noun pattern. This mixed convention lacks a predictable pattern, making the tool set harder to navigate.

Tool Count3/5

With 4 tools, the count is reasonable for a small server, but it feels thin and poorly scoped because it covers two unrelated domains. For either arithmetic or note management alone, 4 tools would be appropriate, but combined, it suggests an incomplete or mismatched purpose.

Completeness2/5

For arithmetic, basic operations like subtraction and division are missing, leaving gaps. For note management, there's no way to list or retrieve notes, creating dead ends. The server lacks a clear domain, making completeness hard to assess, but obvious gaps exist in both inferred areas.

Maintenance

ActivityInactive
ResponsivenessNo issues