|
| 1 | +# Universal Refiner |
| 2 | + |
| 3 | +MCP server for prompt governance. Provides the `refine_prompt` tool that enriches |
| 4 | +prompts with project mandates, agentic context, and semantic refinement via a local |
| 5 | +model or MCP sampling fallback. |
| 6 | + |
| 7 | +## Quick Start |
| 8 | + |
| 9 | +```powershell |
| 10 | +# From the universal-refiner directory |
| 11 | +npm run build |
| 12 | +node dist/src/index.js |
| 13 | +``` |
| 14 | + |
| 15 | +The server registers as an MCP stdio transport. Global registration is managed by |
| 16 | +`scripts/operations/register-global.ps1`. |
| 17 | + |
| 18 | +## Local Model Configuration |
| 19 | + |
| 20 | +`refine_prompt` routes semantic refinement through `LocalOpenAiProvider` first (tier-0), |
| 21 | +then falls back to `McpSamplingProvider` if the local model is unreachable or returns an error. |
| 22 | + |
| 23 | +Configuration is read from `.universal-refiner.json` in the working directory at **server startup**. |
| 24 | +After changing this file you must **restart the MCP server process** for the change to take effect. |
| 25 | + |
| 26 | +### Wiring Ollama / Gemma |
| 27 | + |
| 28 | +1. Start Ollama with the Gemma model: |
| 29 | + |
| 30 | + ```powershell |
| 31 | + ollama pull gemma3:12b |
| 32 | + ollama serve |
| 33 | + ``` |
| 34 | + |
| 35 | + Ollama listens at `http://localhost:11434` by default. |
| 36 | + |
| 37 | +2. Create `.universal-refiner.json` in `universal-refiner/`: |
| 38 | + |
| 39 | + ```json |
| 40 | + { |
| 41 | + "semantic": { |
| 42 | + "localEnabled": true, |
| 43 | + "baseUrl": "http://localhost:11434/v1", |
| 44 | + "models": ["gemma3:12b", "gemma3"], |
| 45 | + "mcpSamplingEnabled": true |
| 46 | + } |
| 47 | + } |
| 48 | + ``` |
| 49 | + |
| 50 | + Copy `.universal-refiner.example.json` as a starting point. |
| 51 | + |
| 52 | +3. Restart the MCP server. |
| 53 | + |
| 54 | +### Config Fields |
| 55 | + |
| 56 | +| Field | Type | Default | Description | |
| 57 | +|-------|------|---------|-------------| |
| 58 | +| `semantic.localEnabled` | boolean | `true` | Enable `LocalOpenAiProvider` as tier-0 | |
| 59 | +| `semantic.baseUrl` | string | `http://localhost:9000/v1` | OpenAI-compatible `/v1` base URL. **Ollama default is port 11434, not 9000.** | |
| 60 | +| `semantic.models` | string[] | `["gemma3:12b", "gemma3:1b"]` | Model names tried in order. First reachable model wins. | |
| 61 | +| `semantic.mcpSamplingEnabled` | boolean | `true` | Fall back to MCP sampling if local model fails | |
| 62 | +| `semantic.timeoutMs` | number | `120000` | Request timeout in milliseconds | |
| 63 | +| `semantic.temperature` | number | `0.2` | Sampling temperature (0–2) | |
| 64 | +| `semantic.allowNonLoopback` | boolean | `false` | Must be `true` for non-loopback base URLs (e.g., remote server). Leave `false` for localhost. | |
| 65 | + |
| 66 | +> **Important:** The hardcoded default `baseUrl` is port 9000, not 11434. Ollama serves on |
| 67 | +> port 11434. Without a `.universal-refiner.json` overriding `baseUrl`, `LocalOpenAiProvider` |
| 68 | +> will silently fail to connect and fall through to MCP sampling. |
| 69 | +
|
| 70 | +### LM Studio |
| 71 | + |
| 72 | +LM Studio exposes the same OpenAI-compatible `/v1` API. Use: |
| 73 | + |
| 74 | +```json |
| 75 | +{ |
| 76 | + "semantic": { |
| 77 | + "localEnabled": true, |
| 78 | + "baseUrl": "http://localhost:1234/v1", |
| 79 | + "models": ["gemma-3-12b-it"] |
| 80 | + } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +### Provider Chain |
| 85 | + |
| 86 | +When a `refine_prompt` call arrives: |
| 87 | + |
| 88 | +1. `LocalOpenAiProvider` is tried first (if `localEnabled: true`). |
| 89 | + - Iterates `models` in order. On model failure, moves to the next model. |
| 90 | + - Returns `null` if all models fail (triggers fallback). |
| 91 | +2. `McpSamplingProvider` is tried next (if `mcpSamplingEnabled: true`). |
| 92 | +3. If both fail, `refine_prompt` returns the original prompt unchanged. |
| 93 | + |
| 94 | +## Configuration File Reference |
| 95 | + |
| 96 | +See `.universal-refiner.example.json` for an annotated template. |
| 97 | + |
| 98 | +## Release Gate |
| 99 | + |
| 100 | +```powershell |
| 101 | +npm run release:verify |
| 102 | +``` |
| 103 | + |
| 104 | +Runs build, 100% test coverage, MCP acceptance, semantic fallback, stress/soak, and audit checks. |
| 105 | + |
| 106 | +## Security |
| 107 | + |
| 108 | +- Never commit `.universal-refiner.json` if it contains sensitive values. |
| 109 | + Add it to `.gitignore` if you customise it beyond the example defaults. |
| 110 | +- `allowNonLoopback: false` (default) prevents the local provider from contacting |
| 111 | + non-loopback hosts, limiting the blast radius of a misconfigured `baseUrl`. |
0 commit comments