213 lines
5.6 KiB
Markdown
213 lines
5.6 KiB
Markdown
# inou MCP Server - Technical Documentation
|
|
|
|
## Overview
|
|
|
|
The inou MCP (Model Context Protocol) server provides direct HTTPS access to health data for LLM integration. **No bridge is required** - Claude (Desktop/web) calls the server directly.
|
|
|
|
## Endpoint
|
|
|
|
**Production:** `https://inou.com/mcp`
|
|
**Staging:** `https://dev.inou.com/mcp`
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────┐
|
|
│ Claude Desktop │
|
|
│ or Web App │
|
|
└────────┬────────┘
|
|
│ HTTPS (Streamable HTTP transport)
|
|
│ OAuth 2.0 Bearer token
|
|
▼
|
|
┌─────────────────┐
|
|
│ inou.com/mcp │
|
|
│ (Portal Service)│
|
|
└────────┬────────┘
|
|
│
|
|
▼
|
|
┌─────────────────┐
|
|
│ lib (RBAC) │
|
|
│ + SQLite DB │
|
|
└─────────────────┘
|
|
```
|
|
|
|
**No bridge, no stdio, no localhost proxy.**
|
|
|
|
## Protocol
|
|
|
|
- **Transport:** Streamable HTTP ([MCP Specification](https://modelcontextprotocol.io/specification/draft/basic/transports#http-with-sse))
|
|
- **Protocol Version:** `2025-06-18`
|
|
- **Server Name:** `inou-health`
|
|
- **Server Version:** `1.0.0`
|
|
|
|
## Authentication
|
|
|
|
### OAuth 2.0 Flow
|
|
|
|
MCP uses standard OAuth 2.0 Authorization Code flow with PKCE:
|
|
|
|
1. **Authorization:** `https://inou.com/oauth/authorize`
|
|
2. **Token Exchange:** `https://inou.com/oauth/token`
|
|
3. **UserInfo:** `https://inou.com/oauth/userinfo`
|
|
4. **Token Revocation:** `https://inou.com/oauth/revoke`
|
|
|
|
### OAuth Metadata Endpoints
|
|
|
|
- **Authorization Server Metadata:** `https://inou.com/.well-known/oauth-authorization-server`
|
|
- **Protected Resource Metadata:** `https://inou.com/.well-known/oauth-protected-resource`
|
|
|
|
### Using Access Tokens
|
|
|
|
MCP requests include the OAuth access token in the Authorization header:
|
|
|
|
```http
|
|
POST /mcp HTTP/1.1
|
|
Host: inou.com
|
|
Authorization: Bearer {access_token}
|
|
Content-Type: application/json
|
|
|
|
```
|
|
|
|
The portal's MCP handler:
|
|
1. Extracts the access token
|
|
2. Looks up the associated dossier (user)
|
|
3. Creates an AccessContext for RBAC enforcement
|
|
4. Routes to the appropriate tool handler
|
|
|
|
## Available Tools
|
|
|
|
All tools enforce RBAC - users can only access data they have permission to view.
|
|
|
|
### Imaging Tools
|
|
|
|
- `list_dossiers` - List accessible patient dossiers
|
|
- `list_studies` - List imaging studies (MRI, CT, X-ray)
|
|
- `list_series` - List series within a study (filter by AX, T1, FLAIR, etc.)
|
|
- `list_slices` - List individual slices with position metadata
|
|
- `fetch_image` - Fetch slice image as base64 PNG (with optional window/level)
|
|
- `fetch_contact_sheet` - Thumbnail grid for navigation (**NOT for diagnosis**)
|
|
|
|
### Lab Tools
|
|
|
|
- `get_categories` - List available data categories with entry counts
|
|
- `query_entries` - Query entries by category (labs, documents, etc.)
|
|
|
|
### Genome Tools
|
|
|
|
- `query_genome` - Query genetic variants by gene, rsid, category, or free-text search
|
|
|
|
### System Tools
|
|
|
|
- `get_version` - Server version info
|
|
|
|
## Implementation
|
|
|
|
The MCP server is implemented in the **portal** service (`portal/mcp_http.go`):
|
|
|
|
- **MCP Request Handler:** `handleMCPRequest()` - routes JSON-RPC calls
|
|
- **Tool Implementations:** `portal/mcp_tools.go` - all 11 tool handlers
|
|
- **OAuth Handlers:** Dynamic client registration, token exchange, userinfo
|
|
- **Session Management:** OAuth sessions stored in database
|
|
|
|
## Security
|
|
|
|
1. **OAuth 2.0** - Standard authorization framework
|
|
2. **RBAC** - All data access enforced at entry level
|
|
3. **FIPS 140-3** - Encryption for data at rest
|
|
4. **Read-Only** - All MCP tools are read-only (no mutations)
|
|
5. **Audit Logging** - All MCP access logged to audit table
|
|
|
|
## Testing
|
|
|
|
### Manual Test (curl)
|
|
|
|
```bash
|
|
# 1. Get an OAuth token (you'll need client credentials)
|
|
curl -X POST https://inou.com/oauth/token \
|
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
-d "grant_type=authorization_code&code={code}&client_id={client_id}&client_secret={client_secret}"
|
|
|
|
# 2. Call MCP with token
|
|
curl -X POST https://inou.com/mcp \
|
|
-H "Authorization: Bearer {access_token}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"jsonrpc": "2.0",
|
|
"id": 1,
|
|
"method": "tools/call",
|
|
"params": {
|
|
"name": "list_dossiers",
|
|
"arguments": {}
|
|
}
|
|
}'
|
|
```
|
|
|
|
### Claude Desktop Integration
|
|
|
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"inou": {
|
|
"url": "https://inou.com/mcp",
|
|
"transport": {
|
|
"type": "http"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Claude Desktop handles OAuth flow automatically.
|
|
|
|
## Development
|
|
|
|
**Local Development:**
|
|
```bash
|
|
# Portal runs on :8081, proxied through nginx at localhost
|
|
# MCP endpoint: https://localhost/mcp
|
|
```
|
|
|
|
**Staging:**
|
|
```bash
|
|
# https://dev.inou.com/mcp
|
|
# Test OAuth with staging credentials
|
|
```
|
|
|
|
**Production:**
|
|
```bash
|
|
# https://inou.com/mcp
|
|
# Production OAuth client registered in database
|
|
```
|
|
|
|
## Related Files
|
|
|
|
- `portal/mcp_http.go` - MCP server implementation
|
|
- `portal/mcp_tools.go` - Tool handlers
|
|
- `portal/oauth.go` - OAuth 2.0 handlers
|
|
- `docs/mcp-usage-examples.md` - Usage examples for end users
|
|
- `docs/anthropic-submission.md` - Connector directory submission
|
|
|
|
## Troubleshooting
|
|
|
|
**Images not loading:**
|
|
- Check OAuth token is valid
|
|
- Verify RBAC permissions (CheckAccess logs)
|
|
- Check object storage has files (du -sh /tank/inou/objects/)
|
|
|
|
**"Unauthorized" errors:**
|
|
- Token expired (tokens are valid for 1 hour)
|
|
- User lacks access to requested dossier
|
|
- Check audit log for access attempts
|
|
|
|
**Empty responses:**
|
|
- RBAC blocking access
|
|
- No data exists for query
|
|
- Check lib logs for errors
|