API and environment reference¶
The browser uses REST routes under /api and sends cookies with credentials: include. External MCP clients use Streamable HTTP at /mcp. Application JSON keys use snake_case; MCP tool schemas retain the protocol's inputSchema field.
Application errors use {"detail":"human readable message"}. Credential values and passwords are never returned in resource summaries. A newly created API key is returned once by its creation endpoint.
Identity and browser sessions¶
| Method and route | Request | Result |
|---|---|---|
POST /api/auth/login |
{email, password} |
{user, csrf_token} and a session cookie |
GET /api/auth/me |
None | {user, csrf_token} |
POST /api/auth/logout |
None | Revokes the current session and clears its cookie |
GET /api/invites/{token} |
None | {email, role, expires_at} |
POST /api/auth/accept-invite |
{token, name, password} |
{user, csrf_token} and a fresh invited-account session |
GET /api/health |
None | {status, chat_configured, store_url, gateway_url} |
The session cookie is HttpOnly with SameSite=Lax. Authenticated browser mutations require X-CSRF-Token. Production deployments enable secure cookies. User summaries include id, email, name, role, created_at and active.
Successful login and invitation acceptance revoke only the browser session they replace. Invalid or used invitations leave the current session unchanged. Browser tabs refresh identity after an account change and clear the previous account's workspace state. Invitation acceptance requires a password of 12 to 256 characters; an invitation expires after two days.
Server registry¶
All authenticated users can see non-secret connection summaries. Registry mutations require an administrator.
| Method and route | Behavior |
|---|---|
GET /api/servers |
Lists connection summaries and discovered tools |
POST /api/servers |
Creates a connection |
PATCH /api/servers/{id} |
Updates editable connection fields |
DELETE /api/servers/{id} |
Deletes a connection |
POST /api/servers/{id}/refresh |
Refreshes discovery |
PATCH /api/servers/{id}/tools/permissions |
Updates per-tool permissions |
A create request uses:
{
"name": "Example service",
"slug": "example",
"url": "https://mcp.example.com/mcp",
"auth_type": "none",
"enabled": true
}
auth_type accepts none, bearer or header. credential and header_name are optional fields for configured authentication. The slug is immutable after creation. A blank or omitted credential on update preserves the current value; clear_credential: true removes it.
Connection summaries include id, name, slug, url, enabled, status, last_error, last_checked_at and tools. Each tool includes name, description, inputSchema and permission. Credential values are excluded.
Tool permissions are read or write. New tools default to administrator-only. To update permissions, send original upstream names:
API keys and team¶
| Method and route | Request or result | Access |
|---|---|---|
GET /api/keys |
Lists key records | Own keys; administrators see all |
POST /api/keys |
{name, user_id?} returns {key, record} |
Members create their own; administrators can select another active user |
DELETE /api/keys/{id} |
Revokes the key | Owner or administrator |
GET /api/members |
Lists user summaries | Administrator |
PATCH /api/members/{id} |
{role?, active?} |
Administrator |
GET /api/invites |
Lists {id, email, role, expires_at, accepted_at} |
Administrator |
POST /api/invites |
{email, role} returns invitation details and invite_url |
Administrator |
Key records contain id, name, prefix, user_id, created_at, last_used_at and revoked_at. Only creation returns the full key. Newly issued keys use the harbor_ prefix; existing cc_ keys remain valid until revoked. The final active administrator cannot be demoted or deactivated. Invitation links must be copied and shared privately; there is no email provider.
Activity and chat¶
GET /api/audit returns {items, total} and accepts these query parameters:
| Parameter | Meaning |
|---|---|
limit |
Page size, default 50; allowed range 1 to 200 |
offset |
Non-negative offset, default 0 |
outcome |
Outcome filter |
server_id |
Upstream filter |
user_id |
User filter for administrators |
Members always see only their own records. Entries include the originating user, server and tool names, timestamp, duration, outcome, error and request ID.
POST /api/chat accepts:
Roles are user or assistant, and the last message must be from the user. A request accepts up to 30 messages, 16,000 characters per message and 40,000 characters in total.
The response contains message and tool_calls. Tool calls include name, arguments, result, is_error and duration_ms. A write proposal also returns confirmation with id, summary, tool_name and arguments.
Send POST /api/chat/confirm with {id, approve} to approve or cancel a proposal. The server binds it to the session and user, enforces its five-minute expiry and one-use limit, and rechecks the reviewed target and current authority. Actual tool calls use the MCP HTTP gateway with a session-derived credential. Responses are not streamed. Missing Gemini configuration produces a useful 503 error instead of a fabricated result.
Service interfaces¶
| Service | Port | Entry point | Health routes |
|---|---|---|---|
| Gateway | 8000 | uvicorn backend.app:app --host 0.0.0.0 --port 8000 |
/health/live, /health/ready |
| MCP upstream | 8001 | python -m upstreams.server |
/health/live, /health/ready |
Each upstream serves MCP at /mcp. UPSTREAM_KIND selects woo, policies or shipping, and UPSTREAM_TOKEN is required. Commerce also needs WOO_URL, WOO_KEY and WOO_SECRET.
Tool-call guards use X-Harbor-Read-Only and X-Harbor-Target. For existing clients, X-Commerce-Read-Only remains accepted: either read-only header set to true restricts writes. X-Commerce-Target is used only when the Harbor target header is absent; conflicting supplied targets are denied and audited. New clients emit only the Harbor headers.
The Helm deployment adds trusted proxy handling to the gateway command. FORWARDED_ALLOW_IPS comes from the chart's narrowly configured ingress proxy CIDRs. Do not trust arbitrary forwarding headers; see operations.
Gateway configuration¶
Configuration is read from environment variables. The chart provides deployed values and Secret references.
| Variable | Purpose or default |
|---|---|
DATABASE_URL |
SQLAlchemy connection URL using postgresql+psycopg:// |
SESSION_SECRET |
Secret used for session-related signatures |
BOOTSTRAP_ADMIN_EMAIL, BOOTSTRAP_ADMIN_PASSWORD, BOOTSTRAP_ADMIN_NAME |
Initial administrator identity |
GEMINI_API_KEY |
Optional; chat is unavailable without it |
GEMINI_MODEL |
Defaults to gemini-3.1-flash-lite |
GEMINI_REQUEST_TIMEOUT_SECONDS |
Provider deadline, default 45 seconds |
CHAT_TIMEOUT_SECONDS |
Chat deadline, default 120 seconds |
STORE_URL |
Browser-facing store URL |
GATEWAY_URL |
Browser/client-facing gateway URL, including /mcp |
INTERNAL_GATEWAY_URL |
Defaults to http://127.0.0.1:8000/mcp |
ALLOWED_ORIGINS |
Comma-separated allowed browser origins |
ALLOWED_INTERNAL_HOSTS |
Comma-separated exact service DNS names trusted as internal upstreams |
SECRET_BACKEND |
kubernetes for deployment; file for local development only |
SECRET_FILE |
Local file-mode path, default .secrets/upstreams.json |
UPSTREAM_CREDENTIAL_SECRET |
Mutable credential Secret, default harbor-upstream-credentials |
POD_NAMESPACE |
Kubernetes namespace, default harbor |
BOOTSTRAP_SERVERS_JSON |
Initial connections and their reviewed read tools |
TOOL_TIMEOUT_SECONDS |
Upstream call deadline, default 15 seconds |
DISCOVERY_TIMEOUT_SECONDS |
Discovery deadline, default 8 seconds |
HEALTH_INTERVAL_SECONDS |
Background health interval, default 15 seconds |
SESSION_HOURS |
Session lifetime, default 12 hours |
SECURE_COOKIES |
Enable for public HTTPS deployment; local default is false |
BOOTSTRAP_SERVERS_JSON contains objects with name, slug, url, credential_key and read_tools. Gateway credentials are stored in the mutable Kubernetes Secret keyed by slug. Upstream pods use separate fixed service-token fields in the application Secret. Bootstrap records completion in PostgreSQL and never recreates connections subsequently deleted by an administrator.
Deployment contract¶
The local ingress serves http://harbor.localhost:8080 and http://store.localhost:8080. The MCP endpoint uses /mcp on the console host. Host port bindings are restricted to loopback.
Local images are harbor:dev for the backend and upstreams, harbor-dashboard:dev for the frontend, and harbor-wordpress:dev for the store. Services are ClusterIP. Only dashboard, gateway and store traffic passes through ingress. The chart includes resource requests/limits, health probes, persistent volumes and NetworkPolicies.
Scripts generate credentials; source and Helm values contain no deployed secrets. Use the operations guide for complete installation, production configuration, backup and recovery instructions.