purecontext-mcp 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_INSTRUCTIONS.md +509 -0
- package/AGENT_INSTRUCTIONS_SHORT.md +97 -0
- package/CHANGELOG.md +212 -0
- package/docs/01-introduction.md +69 -0
- package/docs/02-installation.md +267 -0
- package/docs/03-quick-start.md +135 -0
- package/docs/04-configuration.md +214 -0
- package/docs/05-cli-reference.md +130 -0
- package/docs/06-tools-reference.md +499 -0
- package/docs/07-language-support.md +88 -0
- package/docs/08-framework-adapters.md +324 -0
- package/docs/09-dependency-graph.md +182 -0
- package/docs/10-semantic-search.md +153 -0
- package/docs/11-search-quality.md +110 -0
- package/docs/12-ai-summarization.md +106 -0
- package/docs/13-token-savings.md +110 -0
- package/docs/14-transport-modes.md +167 -0
- package/docs/15-team-setup.md +251 -0
- package/docs/16-docker.md +186 -0
- package/docs/17-web-ui.md +157 -0
- package/docs/18-git-history.md +157 -0
- package/docs/19-cross-repo.md +177 -0
- package/docs/20-architecture-analysis.md +228 -0
- package/docs/21-ecosystem-tools.md +189 -0
- package/docs/22-distribution.md +240 -0
- package/docs/23-performance.md +121 -0
- package/docs/24-security.md +144 -0
- package/docs/25-architecture-overview.md +240 -0
- package/docs/26-troubleshooting.md +234 -0
- package/docs/27-api-stability.md +114 -0
- package/docs/README.md +71 -0
- package/guide/README.md +57 -0
- package/guide/ai-summaries.md +127 -0
- package/guide/code-health.md +190 -0
- package/guide/code-history.md +149 -0
- package/guide/finding-code.md +157 -0
- package/guide/navigating-new-code.md +121 -0
- package/guide/safe-changes.md +156 -0
- package/guide/team-setup.md +191 -0
- package/guide/web-ui.md +154 -0
- package/guide/why-purecontext.md +73 -0
- package/guide/workflow-onboarding.md +114 -0
- package/guide/workflow-pr-review.md +199 -0
- package/guide/workflow-refactoring.md +172 -0
- package/package.json +9 -2
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Search Quality & Ranking
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Keyword search is backed by SQLite FTS5 with a custom relevance ranker and a camelCase/snake_case query preprocessor.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## How keyword search works
|
|
9
|
+
|
|
10
|
+
`search_symbols` and `search_text` use SQLite's **FTS5** (Full-Text Search) virtual table, which provides:
|
|
11
|
+
|
|
12
|
+
- BM25 ranking — frequency-adjusted term weighting
|
|
13
|
+
- Fast full-text matching without table scans
|
|
14
|
+
- Unicode tokenization
|
|
15
|
+
|
|
16
|
+
Before FTS5, keyword search used SQL `LIKE` — which had 0% precision for camelCase names. FTS5 with the preprocessor below fixed this.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Query preprocessor
|
|
21
|
+
|
|
22
|
+
Before a query hits FTS5, it goes through a preprocessor that splits identifiers into component words:
|
|
23
|
+
|
|
24
|
+
| Input query | Preprocessed to |
|
|
25
|
+
|-------------|----------------|
|
|
26
|
+
| `processOrder` | `process order` |
|
|
27
|
+
| `process_order` | `process order` |
|
|
28
|
+
| `HTTPClient` | `http client` |
|
|
29
|
+
| `getUserById` | `get user by id` |
|
|
30
|
+
| `validate-token` | `validate token` |
|
|
31
|
+
| `auth validate` | `auth validate` (already split) |
|
|
32
|
+
|
|
33
|
+
This means `processOrder` and `process_order` are equivalent queries — no need to guess the naming convention.
|
|
34
|
+
|
|
35
|
+
**Phrase search** bypasses splitting. Use quotes for exact matching:
|
|
36
|
+
```
|
|
37
|
+
"processOrder" → matches only "processOrder" literally
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Relevance ranker
|
|
43
|
+
|
|
44
|
+
Results are scored by a multi-factor ranker that adjusts raw BM25 scores:
|
|
45
|
+
|
|
46
|
+
| Factor | Boost | Example |
|
|
47
|
+
|--------|-------|---------|
|
|
48
|
+
| Exact name match | +3.0 | query `"authenticate"` matches symbol named `authenticate` |
|
|
49
|
+
| Name starts-with | +1.5 | query `"auth"` matches `authenticateUser` |
|
|
50
|
+
| Symbol kind filter match | +0.5 | `kind: "function"` filters and boosts |
|
|
51
|
+
| File path proximity | +0.3 | query restricted to `src/auth/**` |
|
|
52
|
+
| BM25 base | 1.0 | FTS5 BM25 score |
|
|
53
|
+
|
|
54
|
+
The ranker ensures that an exact name hit always ranks above a summary-only hit, even if the summary appears more times in the index.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## `search_symbols` vs `search_text`
|
|
59
|
+
|
|
60
|
+
| Tool | Searches | Returns |
|
|
61
|
+
|------|---------|---------|
|
|
62
|
+
| `search_symbols` | Symbol names and summaries | Symbol metadata (no source) |
|
|
63
|
+
| `search_text` | Raw file content (grep-style) | File + line + context snippet |
|
|
64
|
+
|
|
65
|
+
Use `search_symbols` for navigating by identifier. Use `search_text` when you need to find a string that isn't a symbol name — error messages, config values, comments, string literals.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Debug mode
|
|
70
|
+
|
|
71
|
+
Pass `debug: true` to either search tool to get the scoring breakdown in the response:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"query": "authenticateUser",
|
|
76
|
+
"debug": true
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Response includes:
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"symbols": [...],
|
|
84
|
+
"_debug": {
|
|
85
|
+
"preprocessedQuery": "authenticate user",
|
|
86
|
+
"ftsMatches": 12,
|
|
87
|
+
"rankedResults": [
|
|
88
|
+
{
|
|
89
|
+
"name": "authenticateUser",
|
|
90
|
+
"bm25": 4.21,
|
|
91
|
+
"nameBoost": 3.0,
|
|
92
|
+
"finalScore": 7.21
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This is useful for diagnosing why a result ranks unexpectedly high or low.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Search tips
|
|
104
|
+
|
|
105
|
+
- **camelCase and snake_case are equivalent** — `processOrder`, `process_order`, and `process order` all return the same results.
|
|
106
|
+
- **Short queries rank better** — `auth` finds more than `authentication function` because shorter terms match more precisely.
|
|
107
|
+
- **Use `kind` filter to narrow** — `kind: "function"` eliminates class/method noise.
|
|
108
|
+
- **Combine with semantic search** — use `mode: "hybrid"` for the best recall when you're not sure of the exact name.
|
|
109
|
+
- **Scope with `filePath`** — `filePath: "src/auth/**"` restricts to a directory.
|
|
110
|
+
- **For exact strings** — use `search_text` with `is_regex: false` when you need to find a literal string in source.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# AI Summarization
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
AI summarization generates one-line descriptions for symbols that have no docstring. Summaries appear in search results and reduce the need to fetch full source.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Summary priority chain
|
|
9
|
+
|
|
10
|
+
For every symbol, PureContext uses the first successful source in this order:
|
|
11
|
+
|
|
12
|
+
1. **Extracted docstring** — JSDoc `/** */`, Python `"""`, `///`, `@doc`, Haddock, etc. No AI cost.
|
|
13
|
+
2. **Framework-derived** — for recognized patterns: `"Vue component UserCard"`, `"GET /api/users Nuxt server route"`. No AI cost.
|
|
14
|
+
3. **AI-generated** (optional) — requires config. Batched API call to the configured provider.
|
|
15
|
+
4. **Signature fallback** — if AI is disabled or fails: reformatted one-liner from the symbol signature. No AI cost.
|
|
16
|
+
|
|
17
|
+
The result is that well-documented codebases spend almost nothing on AI summarization.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Enabling AI summarization
|
|
22
|
+
|
|
23
|
+
AI summarization is **always disabled by default** and requires two explicit opt-ins:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"ai": {
|
|
28
|
+
"provider": "anthropic",
|
|
29
|
+
"allowRemoteAI": true,
|
|
30
|
+
"apiKey": "${ANTHROPIC_API_KEY}",
|
|
31
|
+
"model": "claude-haiku-4-5-20251001",
|
|
32
|
+
"batchSize": 50
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`allowRemoteAI: true` is a safety gate — without it, no outbound AI API calls are made even if `provider` is set. This prevents accidental API costs during development.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Supported providers
|
|
42
|
+
|
|
43
|
+
| Provider | `ai.provider` value | Recommended model | Notes |
|
|
44
|
+
|----------|---------------------|-------------------|-------|
|
|
45
|
+
| Anthropic | `"anthropic"` | `claude-haiku-4-5-20251001` | Best quality, fast |
|
|
46
|
+
| OpenAI | `"openai"` | `gpt-4o-mini` | Good quality, cost-effective |
|
|
47
|
+
| Google Gemini | `"google"` | `gemini-flash` | Lowest cost per token |
|
|
48
|
+
| OpenAI-compatible | `"openai-compatible"` | any | Ollama, LM Studio, etc. |
|
|
49
|
+
| Disabled | `"none"` | — | Default — no AI calls |
|
|
50
|
+
|
|
51
|
+
### Using a local Ollama model
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"ai": {
|
|
56
|
+
"provider": "openai-compatible",
|
|
57
|
+
"allowRemoteAI": true,
|
|
58
|
+
"endpoint": "http://localhost:11434",
|
|
59
|
+
"model": "llama3.2",
|
|
60
|
+
"batchSize": 10
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Batch mode
|
|
68
|
+
|
|
69
|
+
Symbols are summarized in batches to minimize API round trips. `ai.batchSize` controls how many symbols are sent per request (default: 50).
|
|
70
|
+
|
|
71
|
+
The batch prompt includes all symbol signatures and asks for one-line summaries for each. Responses are parsed and cached in SQLite — no re-generation on repeated `index_folder` calls for unchanged files.
|
|
72
|
+
|
|
73
|
+
**Cost estimate:** A 1,000-symbol project with no docstrings, using Claude Haiku at ~50 symbols/batch:
|
|
74
|
+
- 20 API calls
|
|
75
|
+
- ~10,000 input tokens + ~2,000 output tokens per call
|
|
76
|
+
- Total: ~$0.01–0.05 depending on provider
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Google Gemini Flash
|
|
81
|
+
|
|
82
|
+
Google Gemini Flash offers the lowest cost per token for summarization. Enable it with:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"ai": {
|
|
87
|
+
"provider": "google",
|
|
88
|
+
"allowRemoteAI": true,
|
|
89
|
+
"apiKey": "${GEMINI_API_KEY}",
|
|
90
|
+
"model": "gemini-flash",
|
|
91
|
+
"batchSize": 100
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Gemini Flash supports larger batches than Claude or GPT-4o-mini, reducing the number of API calls.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Cost management tips
|
|
101
|
+
|
|
102
|
+
- **Use the cheapest model** — summaries are short, quality difference between Haiku/Flash/mini and Opus/GPT-4o is negligible.
|
|
103
|
+
- **Only undocumented symbols trigger AI** — a codebase with JSDoc on every function costs almost nothing.
|
|
104
|
+
- **Summaries are cached** — re-indexing unchanged files does not re-summarize.
|
|
105
|
+
- **Set `allowRemoteAI: false` during development** (the default) to avoid accidental charges.
|
|
106
|
+
- **Lower `batchSize` for local models** — local models can handle fewer tokens per call.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Token Savings Tracker
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Every retrieval tool call automatically tracks how many tokens were saved compared to reading full files. The tracker is always on — no configuration required.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## How savings are calculated
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
tokens_saved = max(0, (rawFileBytes - responseBytes) / 4)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- `rawFileBytes` — size of the full file(s) that would have been read
|
|
15
|
+
- `responseBytes` — size of the actual response (symbol source or summary)
|
|
16
|
+
- `4 bytes/token` — approximation using the cl100k_base encoding
|
|
17
|
+
|
|
18
|
+
This is a **conservative estimate** — the actual savings are often higher because agents typically need to read multiple files to locate a symbol, while PureContext returns it directly.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Viewing savings
|
|
23
|
+
|
|
24
|
+
### In every response
|
|
25
|
+
|
|
26
|
+
Savings are included in the `_meta` field of every retrieval tool response:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"symbol": { "name": "authenticateUser", ... },
|
|
31
|
+
"source": "...",
|
|
32
|
+
"_meta": {
|
|
33
|
+
"timing_ms": 3,
|
|
34
|
+
"tokens_saved": 1842,
|
|
35
|
+
"total_tokens_saved": 45231,
|
|
36
|
+
"cost_avoided": {
|
|
37
|
+
"claude_opus_4": 0.028,
|
|
38
|
+
"claude_sonnet_4": 0.006
|
|
39
|
+
},
|
|
40
|
+
"powered_by": "PureContext MCP"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Cumulative stats
|
|
46
|
+
|
|
47
|
+
Use the `get_savings_stats` tool to view totals across the session:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Response:**
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"total_tokens_saved": 1234567,
|
|
58
|
+
"equivalent_context_windows": {
|
|
59
|
+
"claude_200k": 6.17,
|
|
60
|
+
"gpt4_128k": 9.64
|
|
61
|
+
},
|
|
62
|
+
"total_cost_avoided": {
|
|
63
|
+
"claude_opus_4": 18.52,
|
|
64
|
+
"claude_sonnet_4": 3.70,
|
|
65
|
+
"claude_haiku_4": 0.99,
|
|
66
|
+
"gpt4o": 3.09,
|
|
67
|
+
"gpt4o_mini": 0.19
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Interpreting results
|
|
75
|
+
|
|
76
|
+
| Savings % | What it means |
|
|
77
|
+
|-----------|--------------|
|
|
78
|
+
| 90–98% | Typical for well-structured codebases — agents retrieving individual symbols |
|
|
79
|
+
| 70–89% | Normal — some larger functions or files being retrieved whole |
|
|
80
|
+
| < 70% | Check agent tool usage — agents may be calling `get_file_content` for full files, or using `get_repo_outline` frequently |
|
|
81
|
+
|
|
82
|
+
**`equivalent_context_windows`** shows how many full context windows worth of tokens were saved — useful for communicating the value to stakeholders.
|
|
83
|
+
|
|
84
|
+
**`total_cost_avoided`** is the dollar equivalent at published API rates for each model. This is an estimate at the time of the release — actual rates may differ.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Persistence
|
|
89
|
+
|
|
90
|
+
Savings persist to `~/.purecontext/_savings.json` across sessions. They accumulate indefinitely.
|
|
91
|
+
|
|
92
|
+
To reset the counter:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"reset": true
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## What does and does not count
|
|
103
|
+
|
|
104
|
+
| Counts toward savings | Does not count |
|
|
105
|
+
|----------------------|---------------|
|
|
106
|
+
| `get_symbol_source` — returns partial file | `list_repos` — no file content |
|
|
107
|
+
| `get_file_outline` — returns symbols, not file | `search_symbols` — no file content |
|
|
108
|
+
| `get_context_bundle` — returns selected symbols | `get_file_tree` — no file content |
|
|
109
|
+
| `get_blast_radius` — returns file list | `index_folder` — write operation |
|
|
110
|
+
| `get_file_content` with line range | `get_file_content` without range (full file) |
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Transport Modes
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
PureContext supports two transport modes: **stdio** (local, default) and **HTTP/SSE** (team/cloud).
|
|
5
|
+
|
|
6
|
+
## stdio transport (default)
|
|
7
|
+
|
|
8
|
+
The standard transport for Claude Code and other MCP-native clients.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
purecontext-mcp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Claude Code spawns `purecontext-mcp` as a child process and communicates over stdin/stdout using the JSON-RPC MCP protocol. No network, no authentication required.
|
|
15
|
+
|
|
16
|
+
**Claude Code setup:**
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Using npx (recommended)
|
|
20
|
+
claude mcp add purecontext-mcp -- npx purecontext-mcp
|
|
21
|
+
|
|
22
|
+
# Using global install
|
|
23
|
+
claude mcp add purecontext-mcp purecontext-mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Best for:** Individual developers, local development, any situation where security and simplicity matter more than sharing.
|
|
27
|
+
|
|
28
|
+
## HTTP / SSE transport
|
|
29
|
+
|
|
30
|
+
For browser-based clients, remote development, or multi-client setups.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
purecontext-mcp --transport http --port 3000
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or via `config.json`:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"transport": "http",
|
|
41
|
+
"http": {
|
|
42
|
+
"port": 3000,
|
|
43
|
+
"host": "127.0.0.1",
|
|
44
|
+
"corsOrigins": ["http://localhost:*"]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**HTTP endpoints:**
|
|
50
|
+
|
|
51
|
+
| Endpoint | Description |
|
|
52
|
+
|----------|-------------|
|
|
53
|
+
| `GET /health` | Server health check (always public) |
|
|
54
|
+
| `POST /mcp/sse` | MCP Streamable HTTP endpoint |
|
|
55
|
+
| `GET /` | Web UI (served when UI is built) |
|
|
56
|
+
| `GET /admin/*` | Admin API (requires admin key) |
|
|
57
|
+
|
|
58
|
+
**Connect Claude Code to an HTTP server:**
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
// ~/.claude/claude_desktop_config.json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"purecontext": {
|
|
65
|
+
"transport": "http",
|
|
66
|
+
"url": "http://localhost:3000/mcp/sse"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or via CLI:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
claude mcp add purecontext-remote \
|
|
76
|
+
--transport http \
|
|
77
|
+
--url https://purecontext.mycompany.com/mcp/sse \
|
|
78
|
+
--header "Authorization: Bearer pctx_yourkey"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Best for:** Team deployments, shared index, CI pipelines, Web UI access.
|
|
82
|
+
|
|
83
|
+
## Both transports simultaneously (development)
|
|
84
|
+
|
|
85
|
+
Run stdio and HTTP at the same time — useful during development to test the HTTP API while still using Claude Code via stdio:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
purecontext-mcp --transport both
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Choosing a transport
|
|
92
|
+
|
|
93
|
+
| Scenario | Recommended transport |
|
|
94
|
+
|----------|-----------------------|
|
|
95
|
+
| Solo developer, local project | `stdio` |
|
|
96
|
+
| Team with shared codebase | `http` (server) |
|
|
97
|
+
| CI pipeline | `http` or `stdio` with cached index |
|
|
98
|
+
| Web UI access | `http` |
|
|
99
|
+
| Testing both simultaneously | `both` |
|
|
100
|
+
|
|
101
|
+
## Authentication in HTTP mode
|
|
102
|
+
|
|
103
|
+
When binding to a non-loopback address, always enable authentication:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"http": {
|
|
108
|
+
"host": "0.0.0.0",
|
|
109
|
+
"auth": {
|
|
110
|
+
"enabled": true,
|
|
111
|
+
"token": "${PURECONTEXT_API_TOKEN}"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
If `token` is empty and `enabled` is `true`, a random 32-byte hex token is generated at startup and printed to stderr. Save it immediately — it is not persisted to disk.
|
|
118
|
+
|
|
119
|
+
All MCP requests must include:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Authorization: Bearer <token>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
A warning is logged at startup if the server is bound to a non-loopback address with authentication disabled.
|
|
126
|
+
|
|
127
|
+
## TLS / HTTPS
|
|
128
|
+
|
|
129
|
+
PureContext does not terminate TLS itself. Put it behind a reverse proxy for HTTPS in production.
|
|
130
|
+
|
|
131
|
+
**nginx example:**
|
|
132
|
+
|
|
133
|
+
```nginx
|
|
134
|
+
server {
|
|
135
|
+
listen 443 ssl;
|
|
136
|
+
server_name purecontext.mycompany.com;
|
|
137
|
+
|
|
138
|
+
ssl_certificate /etc/letsencrypt/live/purecontext.mycompany.com/fullchain.pem;
|
|
139
|
+
ssl_certificate_key /etc/letsencrypt/live/purecontext.mycompany.com/privkey.pem;
|
|
140
|
+
|
|
141
|
+
location / {
|
|
142
|
+
proxy_pass http://localhost:3000;
|
|
143
|
+
proxy_http_version 1.1;
|
|
144
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
145
|
+
proxy_set_header Connection keep-alive;
|
|
146
|
+
proxy_set_header Host $host;
|
|
147
|
+
# Disable buffering for SSE
|
|
148
|
+
proxy_buffering off;
|
|
149
|
+
proxy_cache off;
|
|
150
|
+
proxy_read_timeout 3600s;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Caddy example:**
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
purecontext.mycompany.com {
|
|
159
|
+
reverse_proxy localhost:3000 {
|
|
160
|
+
flush_interval -1
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## SSE keepalive
|
|
166
|
+
|
|
167
|
+
The HTTP server sends a `: ping` comment over the SSE stream every 30 seconds to keep connections alive through proxies and load balancers. If your proxy has a shorter idle timeout than 30 seconds, increase it (e.g., `proxy_read_timeout 3600s` in nginx).
|