diff --git a/README.md b/README.md index 0ce88c73..dc1b5a47 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Just ask your AI assistant: > *"Find sci-fi movies with 'star wars' in the title released after 2000, show me the genre breakdown, and sort by relevance."* -This Spring AI [Model Context Protocol (MCP)](https://spec.modelcontextprotocol.io/) server exposes Solr operations as tools that any MCP-compatible AI client (Claude Desktop, Claude Code, VS Code/Copilot, Cursor, JetBrains) can invoke. +This Spring AI [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server exposes Solr operations as tools that any MCP-compatible AI client (Claude Desktop, Claude Code, VS Code/Copilot, Cursor, JetBrains) can invoke. ## Quick start @@ -59,11 +59,12 @@ Add the server to your MCP client. For **Claude Desktop**, edit ``` Using a different client, or want STDIO/HTTP/Docker options? See the per-client guides: -**[Claude Code](docs/site/content/pages/mcp/clients/claude-code.md)** · -**[VS Code / Copilot](docs/site/content/pages/mcp/clients/vs-code.md)** · -**[Cursor](docs/site/content/pages/mcp/clients/cursor.md)** · -**[JetBrains](docs/site/content/pages/mcp/clients/jetbrains.md)** · -**[MCP Inspector](docs/site/content/pages/mcp/clients/mcp-inspector.md)**. +**[Claude Desktop](docs/clients/claude-desktop.md)** · +**[Claude Code](docs/clients/claude-code.md)** · +**[VS Code / Copilot](docs/clients/vs-code.md)** · +**[Cursor](docs/clients/cursor.md)** · +**[JetBrains](docs/clients/jetbrains.md)** · +**[MCP Inspector](docs/clients/mcp-inspector.md)**. #### 4. Try it out @@ -146,13 +147,13 @@ The server reads configuration from environment variables. The essentials: | `SOLR_URL` | Solr base URL | `http://localhost:8983/solr/` | | `PROFILES` | Transport mode: `stdio` (default, for Claude Desktop) or `http` (remote / multi-client) | `stdio` | -Running in **HTTP mode** — OAuth2, CORS, and the `HTTP_SECURITY_ENABLED` toggle (secured by default) — is covered in the [security docs](docs/security/). Tracing and metrics env vars (`OTEL_SAMPLING_PROBABILITY`, `OTEL_TRACES_URL`) are covered in [Observability](docs/site/content/pages/mcp/observability.md). +Running in **HTTP mode** — OAuth2, CORS, and the `HTTP_SECURITY_ENABLED` toggle (secured by default) — is covered in the [security docs](docs/security/). Tracing and metrics env vars (`OTEL_SAMPLING_PROBABILITY`, `OTEL_TRACES_URL`) are covered in [Observability](docs/observability.md). ## Documentation **Using it** -- [Quick start](docs/site/content/pages/mcp/quick-start.md) · [Client setup](docs/site/content/pages/mcp/clients/) — Claude Desktop, Claude Code, VS Code, Cursor, JetBrains, MCP Inspector -- [Observability](docs/site/content/pages/mcp/observability.md) — OpenTelemetry traces, metrics, logs +- [Quick start](#quick-start) · [Client setup](docs/clients/) — Claude Desktop, Claude Code, VS Code, Cursor, JetBrains, MCP Inspector +- [Observability](docs/observability.md) — OpenTelemetry traces, metrics, logs - Security: [Deployment model (single-tenant)](docs/security/deployment-model.md) · [STDIO model](docs/security/stdio.md) · [HTTP model](docs/security/http.md) · OAuth2 setup: [Auth0](docs/security/auth0.md) · [Keycloak](docs/security/keycloak.md) **Developing it** diff --git a/docs/clients/README.md b/docs/clients/README.md new file mode 100644 index 00000000..c2c92144 --- /dev/null +++ b/docs/clients/README.md @@ -0,0 +1,19 @@ +# Client Setup Guides + +Per-client instructions for connecting an MCP client to the Solr MCP Server. +Each guide covers the transports the client supports: **STDIO** (the server +runs as a local subprocess — JAR or Docker) and **HTTP** (connect to a running +server's streamable HTTP endpoint at `http://localhost:8080/mcp`). + +| Client | Guide | +|--------|-------| +| Claude Desktop | [claude-desktop.md](claude-desktop.md) | +| Claude Code | [claude-code.md](claude-code.md) | +| VS Code / GitHub Copilot | [vs-code.md](vs-code.md) | +| Cursor | [cursor.md](cursor.md) | +| JetBrains IDEs | [jetbrains.md](jetbrains.md) | +| MCP Inspector | [mcp-inspector.md](mcp-inspector.md) | + +Before connecting, start Solr and build the server — see the +[Quick start](../../README.md#quick-start). For OAuth2 on the HTTP transport, +see the [security docs](../security/). diff --git a/docs/clients/claude-code.md b/docs/clients/claude-code.md new file mode 100644 index 00000000..c05a92a8 --- /dev/null +++ b/docs/clients/claude-code.md @@ -0,0 +1,111 @@ +# Claude Code + +[Claude Code](https://docs.anthropic.com/en/docs/claude-code) is Anthropic's CLI tool for Claude. It supports MCP servers via the `claude mcp add` command or a `.mcp.json` project file. + +*** + +## CLI Syntax ## + +The general form of `claude mcp add` is (see [Claude Code MCP docs](https://code.claude.com/docs/en/mcp)): + +```bash +claude mcp add [options] [args...] +``` + +The server `` comes first. For a **STDIO** server, pass any `-e KEY=value` options (repeatable) after the name, then `--`, then the launch command. The `--` stops Claude Code from reparsing the server's own flags as its own options, and `-e` stops consuming tokens at the `--`: + +```bash +claude mcp add -e KEY=value -- [args...] +``` + +For an **HTTP** server, no `--` is needed — pass the URL with `--transport http`: + +```bash +claude mcp add --transport http +``` + +*** + +## STDIO Mode (Recommended) ## + +### CLI ### + +```bash +# JAR +claude mcp add solr-mcp \ + -e SOLR_URL=http://localhost:8983/solr/ \ + -- java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar + +# Docker (local image — build first with ./gradlew jibDockerBuild) +claude mcp add solr-mcp \ + -- docker run -i --rm -e SOLR_URL=http://host.docker.internal:8983/solr/ \ + solr-mcp:latest +``` + +### `.mcp.json` ### + +Add to your project root: + +**JAR:** + +```json +{ + "mcpServers": { + "solr-mcp": { + "type": "stdio", + "command": "java", + "args": ["-jar", "/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar"], + "env": { "SOLR_URL": "http://localhost:8983/solr/" } + } + } +} +``` + +**Docker (local image):** + +```json +{ + "mcpServers": { + "solr-mcp": { + "type": "stdio", + "command": "docker", + "args": ["run", "-i", "--rm", + "-e", "SOLR_URL=http://host.docker.internal:8983/solr/", + "solr-mcp:latest"] + } + } +} +``` + +**Linux users**: add `"--add-host=host.docker.internal:host-gateway"` to the `args` array. + +*** + +## HTTP Mode ## + +Start the server in HTTP mode first (`PROFILES=http java -jar build/libs/solr-mcp-1.0.0-SNAPSHOT.jar`, or `PROFILES=http ./gradlew bootRun`), then: + +### CLI ### + +```bash +claude mcp add --transport http solr-mcp http://localhost:8080/mcp +``` + +### `.mcp.json` ### + +```json +{ + "mcpServers": { + "solr-mcp": { + "type": "http", + "url": "http://localhost:8080/mcp" + } + } +} +``` + +### Secured HTTP (OAuth2) ### + +Claude Code detects the OAuth2 challenge from the server and initiates the authorization flow automatically. The configuration is the same as unsecured HTTP. + +See the [HTTP security model](../security/http.md) for server-side OAuth2 setup. diff --git a/docs/clients/claude-desktop.md b/docs/clients/claude-desktop.md new file mode 100644 index 00000000..ea985dc5 --- /dev/null +++ b/docs/clients/claude-desktop.md @@ -0,0 +1,107 @@ +# Claude Desktop + +[Claude Desktop](https://claude.ai/download) is Anthropic's desktop application for Claude. It supports MCP servers via STDIO and HTTP transports. + +### Configuration File + +* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` +* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` + +Restart Claude Desktop after any configuration change. + +*** + +## STDIO Mode (Recommended) ## + +STDIO mode communicates via stdin/stdout. This is the simplest setup for local use. + +### JAR ### + +Requires Java 25+ and a [built JAR](../../README.md#quick-start) (`./gradlew build`). + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "java", + "args": ["-jar", "/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar"], + "env": { + "SOLR_URL": "http://localhost:8983/solr/" + } + } + } +} +``` + +### Docker (local image) ### + +Build the image first: `./gradlew jibDockerBuild` + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "docker", + "args": ["run", "-i", "--rm", + "-e", "SOLR_URL=http://host.docker.internal:8983/solr/", + "solr-mcp:latest"] + } + } +} +``` + +**Linux users**: add `"--add-host=host.docker.internal:host-gateway"` to the `args` array. + +*** + +## HTTP Mode ## + +HTTP mode connects to a running MCP server via REST endpoints. Start the server first, then configure Claude Desktop to connect using `mcp-remote`. + +### Start the Server ### + +```bash +# JAR +PROFILES=http java -jar build/libs/solr-mcp-1.0.0-SNAPSHOT.jar + +# Or Gradle +PROFILES=http ./gradlew bootRun + +# Or Docker (local image) +docker run -p 8080:8080 --rm \ + -e PROFILES=http \ + -e SOLR_URL=http://host.docker.internal:8983/solr/ \ + solr-mcp:latest +``` + +### Configure Claude Desktop ### + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "npx", + "args": ["mcp-remote", "http://localhost:8080/mcp"] + } + } +} +``` + +### Secured HTTP (OAuth2) ### + +When OAuth2 is enabled on the server, `mcp-remote` handles the authorization flow automatically—it discovers the authorization server and opens a browser for consent. + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "npx", + "args": ["mcp-remote", "http://localhost:8080/mcp", "--allow-http"] + } + } +} +``` + +The `--allow-http` flag is needed for `http://` URLs (development). Omit it in production with HTTPS. + +See the [HTTP security model](../security/http.md) for server-side OAuth2 setup. diff --git a/docs/clients/cursor.md b/docs/clients/cursor.md new file mode 100644 index 00000000..db756a08 --- /dev/null +++ b/docs/clients/cursor.md @@ -0,0 +1,72 @@ +# Cursor + +[Cursor](https://cursor.sh/) supports MCP servers natively via project configuration files or the Cursor Settings UI. + +*** + +## STDIO Mode (Recommended) ## + +### Project Configuration (`.cursor/mcp.json`) ### + +Create `.cursor/mcp.json` in your project root: + +**JAR:** + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "java", + "args": ["-jar", "/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar"], + "env": { "SOLR_URL": "http://localhost:8983/solr/" } + } + } +} +``` + +**Docker (local image — build first with `./gradlew jibDockerBuild`):** + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "docker", + "args": ["run", "-i", "--rm", + "-e", "SOLR_URL=http://host.docker.internal:8983/solr/", + "solr-mcp:latest"] + } + } +} +``` + +**Linux users**: add `"--add-host=host.docker.internal:host-gateway"` to the `args` array. + +### Cursor Settings UI ### + +1. Open **Cursor Settings** (gear icon or Cmd+, / Ctrl+,) +2. Navigate to **Features** > **MCP Servers** +3. Click **Add New MCP Server** +4. Enter: + * **Name**: `solr-mcp` + * **Type**: `command` + * **Command**: `java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar` + +*** + +## HTTP Mode ## + +Start the server in HTTP mode first (`PROFILES=http java -jar build/libs/solr-mcp-1.0.0-SNAPSHOT.jar`, or `PROFILES=http ./gradlew bootRun`), then: + +```json +{ + "mcpServers": { + "solr-mcp": { + "url": "http://localhost:8080/mcp" + } + } +} +``` + +The configuration is the same for secured and unsecured HTTP. Cursor handles the MCP OAuth2 flow automatically. + +See the [Cursor MCP documentation](https://docs.cursor.com/context/model-context-protocol) for the latest configuration format. diff --git a/docs/clients/jetbrains.md b/docs/clients/jetbrains.md new file mode 100644 index 00000000..84217654 --- /dev/null +++ b/docs/clients/jetbrains.md @@ -0,0 +1,75 @@ +# JetBrains IDEs + +[JetBrains IDEs](https://www.jetbrains.com/) (IntelliJ IDEA, WebStorm, PyCharm, etc.) support MCP servers through the AI Assistant plugin. + +*** + +## STDIO Mode (Recommended) ## + +### Project Configuration (`.junie/mcp/mcp.json`) ### + +Create `.junie/mcp/mcp.json` in your project root: + +**JAR:** + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "java", + "args": ["-jar", "/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar"], + "env": { "SOLR_URL": "http://localhost:8983/solr/" } + } + } +} +``` + +**Docker (local image — build first with `./gradlew jibDockerBuild`):** + +```json +{ + "mcpServers": { + "solr-mcp": { + "command": "docker", + "args": ["run", "-i", "--rm", + "-e", "SOLR_URL=http://host.docker.internal:8983/solr/", + "solr-mcp:latest"] + } + } +} +``` + +**Linux users**: add `"--add-host=host.docker.internal:host-gateway"` to the `args` array. + +### IDE Settings ### + +1. Open **Settings** (Cmd+, / Ctrl+Alt+S) +2. Navigate to **Tools** > **AI Assistant** > **MCP Servers** +3. Click **Add** (`+`) +4. Configure: + * **Name**: `solr-mcp` + * **Transport**: `STDIO` + * **Command**: `java` + * **Arguments**: `-jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar` + +*** + +## HTTP Mode ## + +Start the server in HTTP mode first (`PROFILES=http java -jar build/libs/solr-mcp-1.0.0-SNAPSHOT.jar`, or `PROFILES=http ./gradlew bootRun`), then: + +```json +{ + "mcpServers": { + "solr-mcp": { + "url": "http://localhost:8080/mcp" + } + } +} +``` + +Or in IDE Settings, select the **HTTP** transport and enter `http://localhost:8080/mcp` as the URL. AI Assistant connects using the **Streamable HTTP** transport, which is what this server implements; the legacy SSE transport (a `/sse` URL) is not supported. + +The configuration is the same for secured and unsecured HTTP. JetBrains IDEs handle the MCP OAuth2 flow automatically. + +MCP support requires the AI Assistant plugin. See the [JetBrains MCP documentation](https://www.jetbrains.com/help/ai-assistant/mcp.html) for the latest configuration format. diff --git a/docs/clients/mcp-inspector.md b/docs/clients/mcp-inspector.md new file mode 100644 index 00000000..a21e686d --- /dev/null +++ b/docs/clients/mcp-inspector.md @@ -0,0 +1,56 @@ +# MCP Inspector + +The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is a web-based tool for testing and debugging MCP servers. It lets you browse available tools, invoke them interactively, and inspect responses. + +### Install ### + +```bash +npx @modelcontextprotocol/inspector +``` + +This starts the Inspector UI at `http://localhost:6274`. + +*** + +## STDIO Mode ## + +1. In MCP Inspector, select **STDIO** transport +2. **Command**: `java` +3. **Arguments**: `-jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar` +4. Click **Connect** + +*** + +## HTTP Mode ## + +1. Start the server in HTTP mode: + + # JAR + PROFILES=http java -jar build/libs/solr-mcp-1.0.0-SNAPSHOT.jar + + # Or Gradle + PROFILES=http ./gradlew bootRun + + # Or Docker (local image — build first with ./gradlew jibDockerBuild) + docker run -p 8080:8080 --rm \ + -e PROFILES=http \ + -e SOLR_URL=http://host.docker.internal:8983/solr/ \ + solr-mcp:latest + +2. In MCP Inspector, enter: `http://localhost:8080/mcp` +3. Click **Connect** + +**Linux users** (Docker option): add `--add-host=host.docker.internal:host-gateway` to the `docker run` command. + +*** + +## OAuth2 ## + +When OAuth2 is enabled on the server, configure the Inspector's OAuth settings before connecting: + +1. Click the **OAuth** settings in the Inspector +2. Enter your provider's Authorization URL, Token URL, Client ID, and Redirect URI (`http://localhost:6274/oauth/callback`) +3. Complete the OAuth flow +4. The Inspector will include the Bearer token in all subsequent requests + +See the [HTTP security model](../security/http.md) for server-side OAuth2 setup with [Auth0](../security/auth0.md) and [Keycloak](../security/keycloak.md). diff --git a/docs/clients/vs-code.md b/docs/clients/vs-code.md new file mode 100644 index 00000000..1a15fafc --- /dev/null +++ b/docs/clients/vs-code.md @@ -0,0 +1,82 @@ +# VS Code / GitHub Copilot + +[VS Code](https://code.visualstudio.com/) supports MCP servers through built-in MCP support (VS Code 1.99+). Solr MCP tools are available in GitHub Copilot Chat when using Agent mode. + +*** + +## STDIO Mode (Recommended) ## + +### Workspace Configuration (`.vscode/mcp.json`) ### + +Create `.vscode/mcp.json` in your project root: + +**JAR:** + +```json +{ + "servers": { + "solr-mcp": { + "type": "stdio", + "command": "java", + "args": ["-jar", "/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar"], + "env": { "SOLR_URL": "http://localhost:8983/solr/" } + } + } +} +``` + +**Docker (local image — build first with `./gradlew jibDockerBuild`):** + +```json +{ + "servers": { + "solr-mcp": { + "type": "stdio", + "command": "docker", + "args": ["run", "-i", "--rm", + "-e", "SOLR_URL=http://host.docker.internal:8983/solr/", + "solr-mcp:latest"] + } + } +} +``` + +### User Settings (`settings.json`) ### + +Open VS Code Settings (JSON) and add: + +```json +{ + "mcp": { + "servers": { + "solr-mcp": { + "type": "stdio", + "command": "java", + "args": ["-jar", "/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar"], + "env": { "SOLR_URL": "http://localhost:8983/solr/" } + } + } + } +} +``` + +*** + +## HTTP Mode ## + +Start the server in HTTP mode first (`PROFILES=http java -jar build/libs/solr-mcp-1.0.0-SNAPSHOT.jar`, or `PROFILES=http ./gradlew bootRun`), then: + +```json +{ + "servers": { + "solr-mcp": { + "type": "http", + "url": "http://localhost:8080/mcp" + } + } +} +``` + +The configuration is the same for secured and unsecured HTTP. VS Code handles the MCP OAuth2 flow automatically. + +See the [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for the latest configuration format. diff --git a/docs/observability.md b/docs/observability.md new file mode 100644 index 00000000..b3c17671 --- /dev/null +++ b/docs/observability.md @@ -0,0 +1,111 @@ +# Observability + +## Overview ## + +When running in **HTTP mode**, the Solr MCP Server exports telemetry data via OpenTelemetry to the **LGTM stack** (Loki, Grafana, Tempo, Mimir) for full observability. + +| Signal | Backend | What it shows | +|--------|---------|---------------| +| **Traces** | Tempo | Distributed traces for every MCP tool invocation, Solr query, and HTTP request | +| **Metrics** | Mimir/Prometheus | JVM stats, HTTP request rates, Solr query latencies, cache hit ratios | +| **Logs** | Loki | Structured application logs correlated with trace IDs | + +Every MCP tool invocation creates a trace span: search, indexing (JSON, CSV, XML), collection operations (list, stats, health, create), and schema retrieval. All incoming HTTP requests and outgoing Solr calls are automatically traced. + +*** + +## Setup ## + +### Start the LGTM Stack ### + +The project's `compose.yaml` includes a Grafana OTEL LGTM all-in-one container: + +```bash +docker compose up -d +``` + +This starts: + +| Service | URL | Purpose | +|---------|-----|---------| +| Grafana | http://localhost:3000 | Dashboards and exploration (no auth required) | +| OTLP gRPC | localhost:4317 | Trace/metric/log ingestion (gRPC) | +| OTLP HTTP | localhost:4318 | Trace/metric/log ingestion (HTTP) | + +### Run the Server with Observability ### + +```bash +PROFILES=http ./gradlew bootRun +``` + +The server auto-configures OTLP export when the LGTM stack is running. Default configuration: + +```properties +management.tracing.sampling.probability=1.0 # 100% sampling (dev) +otel.exporter.otlp.endpoint=http://localhost:4317 +otel.exporter.otlp.protocol=grpc +``` + +*** + +## Grafana ## + +Open [http://localhost:3000](http://localhost:3000) and click **Explore** in the left sidebar. + +### View Traces (Tempo) ### + +1. Select **Tempo** as the data source +2. Use TraceQL to search: + + {.service.name="solr-mcp"} + +3. Click on a trace to see the span waterfall—each MCP tool invocation, Solr query, and HTTP request is a separate span + +### View Logs (Loki) ### + +1. Select **Loki** as the data source +2. Use LogQL to search: + + {service_name="solr-mcp"} |= "search" + +3. Logs are automatically correlated with trace IDs—click a log line to jump to its trace + +### View Metrics (Prometheus) ### + +1. Select **Prometheus** as the data source +2. Example queries: + + # HTTP request rate + rate(http_server_requests_seconds_count[5m]) + + # JVM memory usage + jvm_memory_used_bytes + + # Request latency (p99) + histogram_quantile(0.99, rate(http_server_requests_seconds_bucket[5m])) + +*** + +## Actuator Endpoints ## + +The following health and metrics endpoints are exposed in HTTP mode: + +```bash +curl http://localhost:8080/actuator/health # Health check +curl http://localhost:8080/actuator/info # Build info +curl http://localhost:8080/actuator/metrics # Available metrics +curl http://localhost:8080/actuator/prometheus # Prometheus scrape endpoint +curl http://localhost:8080/actuator/loggers # Logger levels +``` + +*** + +## Production Configuration ## + +For production, reduce the sampling rate and configure the OTLP endpoint for your collector: + +```bash +export OTEL_SAMPLING_PROBABILITY=0.1 # 10% sampling +export OTEL_TRACES_URL=https://otel-collector.example.com:4317 +PROFILES=http java -jar build/libs/solr-mcp-1.0.0-SNAPSHOT.jar +``` diff --git a/docs/security/http.md b/docs/security/http.md index 391b9d54..38554387 100644 --- a/docs/security/http.md +++ b/docs/security/http.md @@ -174,5 +174,5 @@ exists for browser-based tooling. - [Deployment model — single-tenant by design](./deployment-model.md) - [STDIO transport security model](./stdio.md) - OAuth2 provider setup: [Auth0](./auth0.md) · [Keycloak](./keycloak.md) -- [GraalVM native image spec](../specs/graalvm-native-image.md) +- [GraalVM native image spec](../../dev-docs/graalvm-native-image.md) - [Logging architecture in `CLAUDE.md`](../../CLAUDE.md#logging-architecture) diff --git a/docs/security/keycloak.md b/docs/security/keycloak.md index 941f2a00..1bf36740 100644 --- a/docs/security/keycloak.md +++ b/docs/security/keycloak.md @@ -17,7 +17,6 @@ This guide covers setting up [Keycloak](https://www.keycloak.org/) as an OAuth2/ - [Testing Authentication](#testing-authentication) - [User Management Options](#user-management-options) - [Manual User Creation](#manual-user-creation) - - [User Federation (LDAP/AD)](#user-federation-ldapad) - [Identity Brokering (GitHub, Google, etc.)](#identity-brokering-github-google-etc) - [Self-Registration](#self-registration) - [REST API](#rest-api) diff --git a/docs/security/stdio.md b/docs/security/stdio.md index e6ec7ec3..c772f536 100644 --- a/docs/security/stdio.md +++ b/docs/security/stdio.md @@ -96,5 +96,5 @@ that launched the process. No code changes are required for STDIO security. - [Deployment model — single-tenant by design](./deployment-model.md) - [HTTP transport security model](./http.md) - OAuth2 provider setup (HTTP mode): [Auth0](./auth0.md) · [Keycloak](./keycloak.md) -- [GraalVM native image spec](../specs/graalvm-native-image.md) +- [GraalVM native image spec](../../dev-docs/graalvm-native-image.md) - [Logging architecture in `CLAUDE.md`](../../CLAUDE.md#logging-architecture)