MCP server for prompt governance. Provides the refine_prompt tool that enriches
prompts with project mandates, agentic context, and semantic refinement via a local
model or MCP sampling fallback.
# From the universal-refiner directory
npm run build
node dist/src/index.jsThe server registers as an MCP stdio transport. Global registration is managed by
scripts/operations/register-global.ps1.
refine_prompt routes semantic refinement through LocalOpenAiProvider first (tier-0),
then falls back to McpSamplingProvider if the local model is unreachable or returns an error.
Configuration is read from .universal-refiner.json in the working directory at server startup.
After changing this file you must restart the MCP server process for the change to take effect.
-
Start Ollama with the Gemma model:
ollama pull gemma3:12b ollama serve
Ollama listens at
http://localhost:11434by default. -
Create
.universal-refiner.jsoninuniversal-refiner/:{ "semantic": { "localEnabled": true, "baseUrl": "http://localhost:11434/v1", "models": ["gemma3:12b", "gemma3"], "mcpSamplingEnabled": true } }Copy
.universal-refiner.example.jsonas a starting point. -
Restart the MCP server.
| Field | Type | Default | Description |
|---|---|---|---|
semantic.localEnabled |
boolean | true |
Enable LocalOpenAiProvider as tier-0 |
semantic.baseUrl |
string | http://localhost:9000/v1 |
OpenAI-compatible /v1 base URL. Ollama default is port 11434, not 9000. |
semantic.models |
string[] | ["gemma3:12b", "gemma3:1b"] |
Model names tried in order. First reachable model wins. |
semantic.mcpSamplingEnabled |
boolean | true |
Fall back to MCP sampling if local model fails |
semantic.timeoutMs |
number | 120000 |
Request timeout in milliseconds |
semantic.temperature |
number | 0.2 |
Sampling temperature (0–2) |
semantic.allowNonLoopback |
boolean | false |
Must be true for non-loopback base URLs (e.g., remote server). Leave false for localhost. |
Important: The hardcoded default
baseUrlis port 9000, not 11434. Ollama serves on port 11434. Without a.universal-refiner.jsonoverridingbaseUrl,LocalOpenAiProviderwill silently fail to connect and fall through to MCP sampling.
LM Studio exposes the same OpenAI-compatible /v1 API. Use:
{
"semantic": {
"localEnabled": true,
"baseUrl": "http://localhost:1234/v1",
"models": ["gemma-3-12b-it"]
}
}When a refine_prompt call arrives:
LocalOpenAiProvideris tried first (iflocalEnabled: true).- Iterates
modelsin order. On model failure, moves to the next model. - Returns
nullif all models fail (triggers fallback).
- Iterates
McpSamplingProvideris tried next (ifmcpSamplingEnabled: true).- If both fail,
refine_promptreturns the original prompt unchanged.
See .universal-refiner.example.json for an annotated template.
npm run release:verifyRuns build, 100% test coverage, MCP acceptance, semantic fallback, stress/soak, and audit checks.
- Never commit
.universal-refiner.jsonif it contains sensitive values. Add it to.gitignoreif you customise it beyond the example defaults. allowNonLoopback: false(default) prevents the local provider from contacting non-loopback hosts, limiting the blast radius of a misconfiguredbaseUrl.