Repo Context Forge
# Repo Context Forge
[](https://glama.ai/mcp/servers/negativexq/repo-context-forge)
[](https://glama.ai/mcp/servers/negativexq/repo-context-forge)
Repo Context Forge is a local-first MCP-based repository intelligence platform. It inspects local codebases through deterministic and security-restricted analyzers, then produces compact, source-grounded context packs for coding agents such as Codex, Claude Code, and Cursor.
Current prerelease: **v0.2.0-alpha.1 - Local Source-Grounded Repository Agent**
## Why This Exists
Coding agents often spend substantial time rebuilding the same repository map,
symbol index, dependency context, and current-state understanding. Repo Context
Forge makes that evidence reusable while preserving repository-relative file and
line references.
The platform operates locally. It does not send repository content to a hosted
model, execute analyzed code, or install dependencies from analyzed projects.
## What It Generates
```text
.context-output/<workspace>/
├── manifest.json
├── project-overview.md
├── repository-map.md
├── architecture.md
├── development-guide.md
├── current-state.md
├── risks-and-debt.md
├── agent-handoff.md
├── symbols.json
├── dependencies.json
├── integrations.json
├── git-state.json
└── bundles/
```
`agent-handoff.md` is the primary compact repository index. Bundles under
`bundles/` gather bounded evidence for a specific objective. Generated context
is an index, not a substitute for inspecting source files before editing them.
## Key Capabilities
- Secure named workspaces with path containment, denied-pattern, symlink, binary,
and file-size controls.
- Deterministic repository trees, metadata, and bounded UTF-8 file reads.
- Lexical text, regex, definition, reference, environment-name, and config-file
search without shell commands.
- Static Python AST symbols, imports, references, callers, callees, and bounded
symbol source ranges without importing analyzed modules.
- Direct dependency declarations, Python internal import graphs, cycle detection,
and rule-based integration evidence.
- Allowlisted read-only local Git status, history, revision comparison, file
history, and changed-symbol analysis.
- Atomic, hash-validated context packs, freshness checks, and deterministic task
bundles.
## Architecture
```mermaid
flowchart TD
A[CLI / MCP Clients] --> B[Application Factories]
B --> C[Repository Intelligence Services]
C --> C1[Repository Access]
C --> C2[Code Search]
C --> C3[Python Symbols]
C --> C4[Dependency Analysis]
C --> C5[Read-Only Git Analysis]
C --> C6[Context Pack Generation]
C1 --> R[Read-Only Mounted Repositories]
C2 --> R
C3 --> R
C4 --> R
C5 --> R
C6 --> O[Writable Context Output]
```
Typer and FastMCP are adapters. Domain services remain independent of both, and
application factories construct explicit dependencies without scanning a
repository during import.
## Quick Start
Prerequisites are Docker Desktop or a compatible Docker Engine with Docker
Compose. Host Python, `uv`, Ruff, mypy, and pytest are not required.
```bash
git clone https://github.com/negativexq/repo-context-forge.git
cd repo-context-forge
docker compose build repo-context-forge
docker compose run --rm repo-context-forge uv run rcf doctor
docker compose run --rm repo-context-forge uv run pytest
```
The development image uses Python 3.12, pinned `uv`, the committed `uv.lock`, a
non-root user, and the project installed in editable mode.
## Mounting Local Repositories
Copy the public examples and replace only the individual host repository paths:
```bash
cp docker-compose.local.example.yml docker-compose.local.yml
cp config.docker.example.yaml config.docker.yaml
```
Example mapping:
```text
Host: /Users/example/projects/service-a
Container: /workspaces/service-a
```
Compose mounts each analyzed repository with `:ro`; configuration always uses
the container path. Never mount an entire home directory, SSH keys, cloud
credentials, Docker credentials, or global Git configuration.
```bash
docker compose \
-f docker-compose.yml \
-f docker-compose.local.yml \
run --rm repo-context-forge \
uv run rcf --config config.docker.yaml workspace list
```
Missing configured mounts fail with a safe invalid-workspace-root error.
## Generating a Context Pack
```bash
docker compose \
-f docker-compose.yml \
-f docker-compose.local.yml \
run --rm repo-context-forge \
uv run rcf --config config.docker.yaml \
context generate service-a
```
Validate integrity and inspect freshness without regenerating:
```bash
docker compose -f docker-compose.yml -f docker-compose.local.yml run --rm repo-context-forge \
uv run rcf --config config.docker.yaml context validate service-a
docker compose -f docker-compose.yml -f docker-compose.local.yml run --rm repo-context-forge \
uv run rcf --config config.docker.yaml context freshness service-a
```
Generated output persists through the writable
`./.context-output:/app/.context-output` mount. Analyzed repository mounts remain
read-only. On macOS Docker Desktop, generated files are visible through the
normal bind-mounted project directory and retain Docker Desktop's mapped host
ownership behavior.
## Creating a Task Bundle
```bash
docker compose -f docker-compose.yml -f docker-compose.local.yml run --rm repo-context-forge \
uv run rcf --config config.docker.yaml \
context bundle service-a inspect-service \
--objective "Understand the service and repository interaction" \
--term service \
--term repository
```
Task bundles rank validated seed files, lexical matches, Python symbols, static
calls and imports, module dependencies, relevant tests, and available local Git
evidence. They do not copy the complete repository.
For a self-contained public demonstration, run:
```bash
make docker-demo
```
This analyzes the synthetic read-only fixture under `examples/demo-repository`,
validates its pack, creates `bundles/understand-service.md`, and lists generated
artifacts.
## MCP Servers
Each FastMCP server runs independently over stdio and accepts `--config`:
Repository MCP tools are read-only, accept repository-relative paths rather
than host filesystem paths, and publish model-oriented parameter guidance in
their generated schemas. Glama server metadata is provided in `glama.json`.
| Entry point | Purpose | Tools |
| --- | --- | ---: |
| `rcf-mcp-repository` | Secure repository files and trees | 6 |
| `rcf-mcp-code-search` | Deterministic lexical search | 6 |
| `rcf-mcp-symbols` | Static Python AST intelligence | 8 |
| `rcf-mcp-dependencies` | Dependency and integration intelligence | 6 |
| `rcf-mcp-git` | Read-only local Git intelligence | 7 |
| `rcf-mcp-context` | Context packs and task bundles | 7 |
Example startup:
```bash
docker compose run --rm -i repo-context-forge \
uv run rcf-mcp-context --config config.docker.yaml
```
Repository tools: `list_workspaces`, `get_repository_tree`, `find_files`,
`read_file`, `read_file_range`, `get_file_metadata`.
Code-search tools: `search_text`, `search_regex`, `find_definitions`,
`find_references`, `find_environment_variables`, `find_config_files`.
Symbol tools: `list_symbols`, `get_symbol`, `find_symbol_definitions`,
`find_symbol_references`, `get_module_imports`, `get_symbol_source`,
`get_callers`, `get_callees`.
Dependency tools: `get_external_dependencies`, `get_internal_dependency_graph`,
`find_dependency_cycles`, `find_external_integrations`,
`get_module_dependencies`, `find_dependency_usage`.
Git tools: `get_repository_state`, `get_git_status`, `get_recent_commits`,
`get_changed_files`, `compare_revisions`, `get_file_history`,
`get_recently_changed_symbols`.
Context tools: `generate_context_pack`, `validate_context_pack`,
`get_context_pack_freshness`, `inspect_context_manifest`,
`create_task_bundle`, `list_context_artifacts`, `read_context_artifact`.
## CLI Reference
All repository-specific commands use one global option:
```bash
rcf --config CONFIG workspace list
rcf --config CONFIG repo tree WORKSPACE
rcf --config CONFIG repo find WORKSPACE PATTERN
rcf --config CONFIG repo read WORKSPACE RELATIVE_PATH
rcf --config CONFIG repo read-range WORKSPACE RELATIVE_PATH START END
rcf --config CONFIG repo metadata WORKSPACE RELATIVE_PATH
rcf --config CONFIG search text WORKSPACE QUERY
rcf --config CONFIG search regex WORKSPACE PATTERN
rcf --config CONFIG search definitions WORKSPACE NAME
rcf --config CONFIG search references WORKSPACE NAME
rcf --config CONFIG search env WORKSPACE
rcf --config CONFIG search config-files WORKSPACE
rcf --config CONFIG symbols list WORKSPACE
rcf --config CONFIG symbols find WORKSPACE NAME
rcf --config CONFIG symbols get WORKSPACE QUALIFIED_NAME
rcf --config CONFIG symbols references WORKSPACE NAME
rcf --config CONFIG symbols imports WORKSPACE RELATIVE_PATH
rcf --config CONFIG symbols source WORKSPACE QUALIFIED_NAME
rcf --config CONFIG symbols callers WORKSPACE NAME
rcf --config CONFIG symbols callees WORKSPACE QUALIFIED_NAME
rcf --config CONFIG dependencies list WORKSPACE
rcf --config CONFIG dependencies graph WORKSPACE
rcf --config CONFIG dependencies cycles WORKSPACE
rcf --config CONFIG dependencies integrations WORKSPACE
rcf --config CONFIG dependencies module WORKSPACE MODULE_OR_PATH
rcf --config CONFIG dependencies usage WORKSPACE DEPENDENCY
rcf --config CONFIG git state WORKSPACE
rcf --config CONFIG git status WORKSPACE
rcf --config CONFIG git log WORKSPACE
rcf --config CONFIG git changed-files WORKSPACE
rcf --config CONFIG git compare WORKSPACE BASE TARGET
rcf --config CONFIG git file-history WORKSPACE RELATIVE_PATH
rcf --config CONFIG git changed-symbols WORKSPACE
rcf --config CONFIG context generate WORKSPACE
rcf --config CONFIG context validate WORKSPACE
rcf --config CONFIG context freshness WORKSPACE
rcf --config CONFIG context manifest WORKSPACE
rcf --config CONFIG context list WORKSPACE
rcf --config CONFIG context read WORKSPACE ARTIFACT
rcf --config CONFIG context bundle WORKSPACE NAME --objective OBJECTIVE
```
`rcf --version` and `rcf doctor` do not inspect repositories. Workspace
registration mutations remain service-level and in-memory; the CLI exposes only
`workspace list` rather than misleading non-persistent add/remove commands.
## Security Model
- Every repository path is resolved and checked for containment after symlink
resolution.
- POSIX and Windows absolute paths, traversal, external symlinks, denied files,
directories-as-files, oversized files, binary data, and invalid UTF-8 are
rejected.
- Denied patterns such as `.env`, `*.pem`, `*.key`, `.git`, `node_modules`, and
virtual environments take precedence over analysis patterns.
- Repository-wide scans are deterministic and bounded. Explicit denied reads
fail rather than returning misleading empty results.
- Analyzed modules and dependency manifests are never imported or executed.
- Git is the only subprocess boundary. It uses argument lists, `shell=False`, a
controlled environment, time/output bounds, and allowlisted read-only commands.
- Context output has a separate containment policy, fixed artifact names, atomic
replacement, and validated SHA-256 manifest hashes.
- The container has no Docker socket, privileged mode, host networking, SSH
forwarding, cloud credentials, or writable analyzed-repository mounts.
See [SECURITY.md](SECURITY.md) for vulnerability reporting.
## Deterministic Analysis and Limitations
Lexical search may include comments and strings and does not resolve symbol
identity. Python AST analysis excludes comments and strings but cannot fully
resolve dynamic dispatch, reflection, aliases, or dynamic imports. Only Python
has AST symbol support.
Dependency intelligence parses direct declarations from `pyproject.toml`,
requirements files, `setup.cfg`, static literal `setup.py`, and `package.json`.
It does not resolve transitive dependencies. Docker and Compose are parsed only
as infrastructure evidence. Integration detection is explicit and rule-based.
Git analysis is local and read-only. It returns metadata and changed ranges, not
full patches or remote state. Context classifications and architectural
interpretations are marked as inferences. Packs can become stale after source,
Git, configuration, or generator changes. The alpha local agent remains
deterministic at its security boundaries but model behavior is not guaranteed.
No embeddings, semantic search, remote API, or web UI are included.
## Experimental Local LLM Provider
The `v0.2.0-alpha.1` prerelease adds local model connectivity, normal chat,
structured tool calls, and a bounded read-only repository agent. It does not
enrich context packs or permit repository mutation.
### Start Ollama
Ollama is optional and pinned under the Compose `llm` profile. Its host port is
bound only to loopback.
```bash
docker compose --profile llm up -d ollama
```
### Pull a Model
Model downloads are always explicit and may require several gigabytes.
```bash
docker compose --profile llm exec ollama \
ollama pull qwen3:4b
```
The equivalent Make targets are `make docker-ollama-up`,
`make docker-model-pull MODEL=qwen3:4b`, and `make docker-model-list`.
### Configure the Model
Container commands use the Compose service hostname:
```yaml
models:
default: qwen-local
providers:
qwen-local:
provider: ollama
model: qwen3:4b
base_url: http://ollama:11434/v1
api_key: ollama
enabled: true
tool_calling: true
context_window: 32768
request_timeout_seconds: 120
temperature: 0
max_output_tokens: 2048
```
`api_key: ollama` is the conventional non-secret placeholder for the local
OpenAI-compatible endpoint. Real keys are excluded from public summaries and
must never be committed.
### Check Model Health
```bash
docker compose --profile llm run --rm repo-context-forge \
uv run rcf --config config.docker.yaml models health qwen-local
```
### Run a Chat Test
```bash
docker compose --profile llm run --rm repo-context-forge \
uv run rcf --config config.docker.yaml \
models chat qwen-local "Reply with the word READY."
```
### Run a Tool-Call Test
```bash
docker compose --profile llm run --rm repo-context-forge \
uv run rcf --config config.docker.yaml models tool-test qwen-local
```
The test asks for `find_symbol_definitions` with synthetic arguments and only
prints the validated call. Tool-calling reliability varies by model, especially
for smaller models.
### Host vs Container URLs
Use `http://ollama:11434/v1` from the application container. Use
`http://127.0.0.1:11434/v1` for a host-side CLI. Container configuration must
not use `localhost`, and Compose does not use host networking.
### Current Limitations
- Model pulling is manual and never occurs during application startup or tests.
- Only Ollama's OpenAI-compatible local endpoint is supported.
- Agent execution is stateless, sequential, and read-only; context-pack model
enrichment is not implemented.
- Provider output and tool arguments remain untrusted and strictly validated.
- Live tests are opt-in: `RCF_RUN_OLLAMA_TESTS=1 uv run pytest -m ollama_live`.
## Experimental MCP Client Runtime
The MCP client runtime starts explicitly configured local servers over stdio,
discovers and namespaces their tools, validates call arguments, and normalizes
bounded results. MCP commands remain available for manual inspection; the agent
uses the same manager and validation boundary for model-requested calls.
The six configured servers currently expose 40 tools in total.
### Configure MCP Servers
`config.docker.example.yaml` defines the six existing servers using explicit
argument lists. Configuration loading starts no process. Only `stdio` transport
is accepted, namespaces must be unique, and disabled servers are skipped.
```yaml
mcp:
default_tool_timeout_seconds: 20
startup_timeout_seconds: 15
shutdown_timeout_seconds: 5
max_tool_result_chars: 30000
servers:
symbols:
transport: stdio
command: uv
args: [run, rcf-mcp-symbols, --config, /app/config.docker.yaml]
enabled: true
namespace: symbols
allowed_tools: ["*"]
```
MCP server stdout is reserved for protocol messages. Diagnostics must use
stderr. Child processes receive a conservative runtime environment plus only
explicitly configured values.
### Inspect Configured Servers
This reads configuration without starting child processes:
```bash
docker compose run --rm repo-context-forge \
uv run rcf --config config.docker.yaml mcp servers
```
### Check MCP Health
```bash
docker compose run --rm repo-context-forge \
uv run rcf --config config.docker.yaml mcp health
```
Health checks eagerly initialize enabled servers, report independent failures,
and close every session before returning.
### Discover Tools
```bash
docker compose run --rm repo-context-forge \
uv run rcf --config config.docker.yaml mcp tools
```
Canonical names use `<namespace>.<tool>`, such as
`symbols.find_symbol_definitions`. Ordering is deterministic and denied tools
are omitted.
### Inspect a Tool Schema
```bash
docker compose run --rm repo-context-forge \
uv run rcf --config config.docker.yaml \
mcp tool symbols.find_symbol_definitions
```
### Call a Tool Manually
```bash
docker compose run --rm repo-context-forge \
uv run rcf --config config.docker.yaml \
mcp call symbols.find_symbol_definitions \
--arguments '{"workspace":"demo","name":"RepositoryService"}'
```
Arguments must be a JSON object and are validated against the discovered schema
without coercion before one request is sent. MCP error results produce a
non-zero status. Resources and URLs in results are never fetched.
### Export LLM Tool Definitions
```bash
docker compose run --rm repo-context-forge \
uv run rcf --config config.docker.yaml mcp llm-tools
```
OpenAI-compatible function names use reversible `namespace__tool` encoding, for
example `symbols__find_symbol_definitions`; canonical MCP routing continues to
use `symbols.find_symbol_definitions`. This command does not contact a model.
### Current Limitations
Only local stdio child processes are supported. There is no HTTP/SSE transport,
automatic retry, remote server discovery, or conversation persistence. Tool
configuration is trusted local input, while tool
schemas, arguments, and results are untrusted and bounded. Existing repository
and read-only Git policies continue to apply.
## Experimental Local Repository Agent
The development branch includes a stateless, read-only loop that connects the
local model provider to discovered MCP tools. It does not modify repositories,
run shell commands, or permit the model to change process configuration.
The default policy exposes 38 read-only tools and excludes the two
context-output-writing tools.
### Start Ollama
```bash
docker compose --profile llm up -d ollama
docker compose --profile llm exec ollama ollama list
```
Model downloads remain an explicit user action; see the local-provider section
above.
### Configure the Agent
The `agent` configuration bounds iterations, calls, messages, results, answers,
and source references. `default_model` falls back to `models.default` when
omitted. Parallel calls are disabled. The selected workspace must exist before
the provider or MCP processes start.
```yaml
agent:
default_model: qwen-local
max_tool_iterations: 8
max_tool_calls_per_iteration: 4
max_total_tool_calls: 20
max_total_tool_result_chars: 120000
require_sources_for_repository_claims: true
allow_parallel_tool_calls: false
duplicate_tool_call_limit: 2
```
### Ask a Repository Question
```bash
docker compose --profile llm run --rm repo-context-forge \
uv run rcf --config config.docker.yaml \
agent ask demo \
"Where is WidgetRepository defined?"
```
### Inspect the Tool Trace
```bash
docker compose --profile llm run --rm repo-context-forge \
uv run rcf --config config.docker.yaml \
agent trace demo \
"Explain how the demo service reaches the repository layer."
```
The trace contains bounded iteration, tool-name, status, duration, and result
size metadata. It omits prompts, complete tool results, API keys, child stderr,
and raw provider payloads.
### Restrict Servers and Tools
Request filters only reduce locally configured permissions:
```bash
uv run rcf --config config.docker.yaml agent ask demo \
"Where is WidgetRepository defined?" \
--server symbols \
--tool symbols.find_symbol_definitions
```
Use `agent tools demo` with the same filters to inspect the resulting
LLM-facing tool set without calling a model.
### Source-Grounding Behavior
Repository citations are checked against source paths and line ranges observed
in normalized MCP results. Unsupported citations are reported rather than
accepted. If a small model omits citations but valid evidence was collected,
the runtime appends a bounded `Sources used` list deterministically; this list
does not claim that every source supports every sentence.
### Read-Only Security Model
The workspace is fixed for one run and injected only into tools that declare a
`workspace` parameter. Conflicting workspace arguments are rejected. Calls are
schema-validated, sequential, bounded, and routed only through discovered local
tools. `context.generate_context_pack` and `context.create_task_bundle` are
excluded from the default agent policy because they write context output.
### Current Limitations
Small-model tool selection and citation quality vary. Analysis remains lexical
or static where documented and does not resolve dynamic runtime behavior. There
is no conversation persistence, automatic repository editing, cloud provider,
semantic retrieval, evaluation framework, or multi-agent orchestration.
The opt-in live test never downloads a model and is skipped by default:
```bash
RCF_RUN_OLLAMA_AGENT_TESTS=1 uv run pytest -m ollama_agent_live
```
## Development
```bash
make docker-build
make docker-format
make docker-lint
make docker-typecheck
make docker-test
make docker-check
make docker-doctor
```
Local `uv` commands remain available, but Docker is the supported validation
environment. See [CONTRIBUTING.md](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md)
for engineering and source-grounding rules.
## Test and Quality Status
The `v0.2.0-alpha.1` prerelease was verified in Docker:
```text
Python 3.12
206 tests passed
2 opt-in Ollama tests skipped
87% coverage
Ruff passed
mypy passed
```
The public CI workflow repeats formatting, linting, strict typing, and tests with
coverage on pushes and pull requests.
## Roadmap
Future directions are documented in [docs/ROADMAP.md](docs/ROADMAP.md). They are
plans, not commitments. Evaluation remains the next milestone after this alpha.
## License
Repo Context Forge is available under the [MIT License](LICENSE).
TDQS
Scored across 6 tools
Each tool targets a distinct aspect: workspace discovery, structural overview, pattern-based file search, whole-file reading, precise line-range reading, and metadata retrieval. read_file and read_file_range are differentiated by their descriptions, making selection unambiguous.
All tool names follow a consistent verb_noun pattern in snake_case, using clear verbs (list, get, find, read) and specific nouns. This makes the tool set predictable and easy to navigate.
With six tools, the server is well-scoped for a repository context purpose. Each tool occupies a clear niche with no redundancy, and the count is within the ideal range for a focused utility.
The set covers the main workflow: workspace discovery, structure mapping, file search, content reading (whole and partial), and metadata. A content-search (grep-like) tool is a minor gap, but the current surface handles typical repository inspection tasks effectively.