Skip to main content
Glama
Grimkey

raw-mcp

by Grimkey
README.md
# raw_mcp

A minimal [Model Context Protocol](https://modelcontextprotocol.io) server written
in **pure Python** — no MCP SDK, no third-party libraries. It speaks JSON-RPC 2.0
over stdio, which is how MCP clients talk to servers they launch as a subprocess.

## Prerequisites

- [uv](https://docs.astral.sh/uv/) (`brew install uv`)

## Layout

- `server.py` — the MCP server (stdlib only)
- `test_server.py` — a smoke test that drives the server through a full handshake
- `pyproject.toml` — uv project metadata (no runtime dependencies)

## Run the tests

```sh
uv run test_server.py
```

## Run the server manually

The server reads JSON-RPC from stdin and writes responses to stdout, so you can
poke at it by hand:

```sh
uv run server.py
```

Then paste a line and press enter:

```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}
```

Diagnostic logs go to **stderr** so they never corrupt the JSON on stdout.

## Use it from an MCP client

Point any MCP client (Claude Desktop, etc.) at the server via uv. Example
`claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "raw-mcp": {
      "command": "uv",
      "args": ["run", "server.py"],
      "cwd": "/Users/jameswhite/conductor/workspaces/raw_mcp/san-salvador"
    }
  }
}
```

## Use it from Claude Code

Register the server with Claude Code's MCP support, then call the tool from a
session.

### Add the server

```sh
claude mcp add raw-mcp -- uv run --directory /Users/jameswhite/conductor/workspaces/raw_mcp/san-salvador server.py
```

- `raw-mcp` is the name it shows up as.
- Everything after `--` is the launch command. Using `uv run --directory <path>`
  means it works regardless of which directory you start Claude Code from. If you
  always launch from this folder, `claude mcp add raw-mcp -- uv run server.py` is
  enough.
- Default scope is `local` (just you, this project). Add `-s user` to make it
  available everywhere, or `-s project` to share it via a committed `.mcp.json`.

### Verify it connected

```sh
claude mcp list          # shows configured servers + connection status
claude mcp get raw-mcp   # shows the launch command for this one
```

`raw-mcp` should report `✔ Connected`.

### Use it

MCP servers are loaded at session startup, so open a fresh interactive Claude Code
session (or restart your current one), then:

- Run `/mcp` — you should see `raw-mcp` connected with one tool,
  `calculate_length`.
- Ask Claude to use it, e.g. *"Use the raw-mcp calculate_length tool on the string
  'hello world'."* The tool is exposed as `mcp__raw-mcp__calculate_length`.

### Remove it when done

```sh
claude mcp remove raw-mcp
```

## The one tool

`calculate_length` — returns the character count of a string.

## How it works

1. **initialize** — the handshake. The server advertises `protocolVersion` and its
   `tools` capability.
2. **notifications/initialized** — the client acknowledges. It's a *notification*
   (no `id`), so the server sends nothing back.
3. **tools/list** — the server returns its tool definitions and JSON schemas.
4. **tools/call** — the client invokes a tool; the server returns `content` blocks.

Adding a tool is two steps: append its definition to `TOOLS`, then handle its name
in `call_tool`.

TDQS

A3.6/5.0

Scored across 1 tool

Disambiguation5/5

Only one tool exists, so there is no possibility of confusing it with another tool. The tool's purpose is clearly defined and isolated.

Naming Consistency5/5

The single tool name follows a clear verb_noun pattern (calculate_length), which is internally consistent and self-explanatory.

Tool Count1/5

A single trivial tool for character counting is extremely thin for a server and feels like a placeholder rather than a coherent toolset.

Completeness1/5

The server provides only string length calculation, leaving substantial gaps for any raw string manipulation tasks. The domain is severely underrepresented, offering a dead-end surface.