Building Your Own MCP Server for AI
Authentication and Secrets
Store API keys and user credentials in the environment, understand OAuth at a high level, and never echo secrets to the model.
Anything you return from a tool can appear in the chat, logs, and the host’s transcript. Treat tool results as public to the human in that session. Secrets stay in the process environment or a secret manager — not in docstrings, not in default arguments.
Environment variables
Read keys at startup or on each call:
import os
import httpx
from mcp.server.mcpserver import MCPServer
mcp = MCPServer("github-lite")
@mcp.tool()
def github_me() -> dict:
'''Return the authenticated GitHub login. Requires GITHUB_TOKEN in the environment.'''
token = os.environ.get("GITHUB_TOKEN", "").strip()
if not token:
return {"ok": False, "error": "GITHUB_TOKEN is not set on the server"}
headers = {
"Authorization": f"Bearer {token}",
"User-Agent": "geek-university-mcp-course/1.0",
"Accept": "application/vnd.github+json",
}
with httpx.Client(timeout=10.0, headers=headers) as client:
response = client.get("https://api.github.com/user")
if response.status_code >= 400:
return {"ok": False, "status": response.status_code, "error": "GitHub rejected the token"}
data = response.json()
return {"ok": True, "login": data.get("login")}In Cursor MCP config, pass env into the child process:
{
"mcpServers": {
"github-lite": {
"command": "/abs/path/.venv/bin/python",
"args": ["/abs/path/server.py"],
"env": { "GITHUB_TOKEN": "ghp_use_a_real_secret_store" }
}
}
}OAuth, briefly
OAuth is for user access (“this person allowed my app to read their calendar”). The MCP server then holds a delegated token, not the user’s password. The dance (redirect, code, refresh token) usually lives in a small web app or the host. Your MCP tools only send Authorization: Bearer …. Do not implement a full OAuth client inside a stdio hello-world.
User credentials versus service credentials
- Service token — one bot identity for the server (CI, a shared GitHub app). Simple, easy to over-scope.
- Per-user token — the host or your login flow supplies a token for that person. Harder, safer for “their” data.
Never log the token. Never return it in a tool result. If you must debug, log token[-4:] only. Next: shape a multi-endpoint API into a few tools.