NORA Data MCP Server
Read-only MCP server that exposes NORA Dashboard data from Upstash Redis.
Prerequisites
- Python 3.10+ (the
mcppackage requires it) - uv (recommended) or pip
Setup
-
Copy
.env.exampleto.envand fill in the Upstash Redis credentials:cp .env.example .env -
Install dependencies:
# With uv (recommended — handles Python version automatically): uv sync # Or with pip: pip install -e .
Running Locally (stdio transport)
# With uv:
uv run python server.py
# Or directly:
python server.py
Claude Desktop Configuration
Add to your Claude Desktop MCP config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"nora-data": {
"command": "uv",
"args": ["run", "--directory", "/Users/ahale/nora-mcp-server", "python", "server.py"],
"env": {
"KV_REST_API_URL": "https://your-redis-instance.upstash.io",
"KV_REST_API_READ_ONLY_TOKEN": "your-read-only-token"
}
}
}
}
Claude Code Configuration
Add to your Claude Code MCP settings:
{
"mcpServers": {
"nora-data": {
"command": "uv",
"args": ["run", "--directory", "/Users/ahale/nora-mcp-server", "python", "server.py"],
"env": {
"KV_REST_API_URL": "https://your-redis-instance.upstash.io",
"KV_REST_API_READ_ONLY_TOKEN": "your-read-only-token"
}
}
}
}
Remote Deployment (Hosted Mode)
The server supports streamable-http transport for remote access. When deployed, team members can connect to it without running anything locally.
Deploy to Railway
- Push this repo to GitHub
- Create a new project on Railway
- Connect the GitHub repo
- Add environment variables in Railway dashboard:
KV_REST_API_URL— your Upstash Redis URLKV_REST_API_READ_ONLY_TOKEN— your read-only tokenMCP_TRANSPORT—streamable-http(set automatically via Dockerfile)PORT— Railway sets this automatically
- Deploy — Railway will build from the Dockerfile
Docker Build & Run
docker build -t nora-mcp-server .
docker run -p 8000:8000 \
-e KV_REST_API_URL="https://your-redis-instance.upstash.io" \
-e KV_REST_API_READ_ONLY_TOKEN="your-read-only-token" \
nora-mcp-server
Connecting via Cowork / Claude Code (Remote)
Once deployed, team members add the remote MCP server in their project settings:
{
"mcpServers": {
"nora-data": {
"type": "url",
"url": "https://your-deployed-url.up.railway.app/mcp/"
}
}
}
The streamable-http transport serves the MCP endpoint at /mcp/ by default.
Security Note
The server is read-only (it only reads from Upstash Redis with a read-only token). Authentication is not currently implemented — access control relies on URL obscurity and hosting platform network settings. Add bearer token auth if the server is exposed to the public internet.
Available Tools
| Tool | Description |
|---|---|
get_data_status | Health check — record counts for all tables |
get_okrs | Full OKR tree (objectives + key results + linked initiatives) |
get_key_results | Key results (optional filter: objective_id) |
get_initiatives | Initiatives (optional filters: key_result_id, bu_id) |
get_okr_initiative_links | OKR-to-initiative link records |
get_flags | WBR flags/risks (optional filter: status) |
get_bu_portfolio | Business unit portfolio overview |
get_kpis | KPI metrics (optional filter: initiative_id) |
get_financial_summary | Financial summary (optional filter: bu_id) |
get_northstar_metrics | North Star metrics (optional filter: bu_id) |
get_business_units | All business units |
Architecture
- Transport: stdio (local) or streamable-http (hosted)
- Data source: Upstash Redis REST API (read-only token)
- Redis key pattern:
prod:table:{name}.json - Caching: Per-request cache (tables fetched once per tool call, not persisted)
- Error handling: All tools return JSON; errors are returned as
{"error": "..."}, never thrown