own-mcp-server
by luisspanner
README.md
# own-mcp-server
A personal MCP (Model Context Protocol) server that wraps my own projects as
tools Claude can call directly from chat/Cowork — a meta-project for
connecting the rest of my work into one place, one wrapped project at a
time. Built to learn MCP hands-on by running one, not by reading about it.
First wrapped project: **Internship Copilot**
(`../Internship_Copilot`) — job posting analysis, fit scoring, and
application tracking.
## Setup
```bash
uv sync
```
Internship Copilot's LLM backend (completions + embeddings) is configured
independently, via its own `.env` — see its README. `own-mcp-server` doesn't
care which backend is behind it.
Registered with Claude Code at user scope:
```bash
claude mcp add --scope user own-mcp-server -- uv run --directory <this dir> own-mcp-server
```
## Transports
Two ways to run it:
- **stdio** (`own-mcp-server`) — a local subprocess Claude Code launches
directly. No networking, no auth needed; simplest for local dev.
- **streamable-http** (`own-mcp-server-http`) — an HTTP server for remote
clients (claude.ai web chat can't reach a stdio server on your machine).
Gated by a static bearer token (`MCP_BEARER_TOKEN`) checked in
`http_auth.py`'s ASGI middleware, rather than the MCP SDK's built-in OAuth
machinery — appropriate for a single trusted client, not a multi-tenant
service. The bind host is configurable (`MCP_HTTP_HOST`) since where
`127.0.0.1` is "safe" depends on where the process's actual network
isolation boundary is (bare host vs. a container network behind a reverse
proxy) — see the docstring in `server.py`.
## Architecture
Every wrapped project lives under `src/own_mcp_server/modules/<name>/` and
exposes a single `register(mcp: MCPServer) -> None` function. `server.py`
just imports each module and calls `register` — adding project #2 means
writing a new module package, not touching the core.
## MCP concepts, as learned building this
- **Tool** = a callable action (`analyze_posting`, `add_application`).
Claude decides when to invoke it based on the description/docstring.
- **Resource** = readable data Claude can pull in as context without it
being a callable action (`profile://current`, `applications://all`).
- **Transport**: started with stdio (a local subprocess Claude Code
launches directly) — no networking or auth to build for a first server.
HTTP/SSE would matter if this needed to be reachable remotely.
- The SDK in use here (`mcp` 2.0.0) renamed the old `FastMCP` class to
`MCPServer` (`from mcp.server import MCPServer`) — worth knowing if
following older MCP tutorials that reference `FastMCP`.
## Status
- Core loop implemented for real: `analyze_posting`, `prep_interview`,
`list_applications`, `get_application`, `add_application`,
`update_application_status`, `delete_application`, plus the
`profile://current` and `applications://all` resources.
- Still stubbed (raise `NotImplementedError`): CV import
(`draft_profile_from_cv`), batch ingestion (`batch_analyze_postings`),
profile CRUD beyond read (`add_profile_skill`, `add_profile_project`),
and the eval harness (`run_evaluation`).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues