inquisitor-mcp 0.1.0__tar.gz
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.
- inquisitor_mcp-0.1.0/.claude/settings.local.json +5 -0
- inquisitor_mcp-0.1.0/.claude-plugin/marketplace.json +16 -0
- inquisitor_mcp-0.1.0/.claude-plugin/plugin.json +14 -0
- inquisitor_mcp-0.1.0/.github/workflows/ci.yml +33 -0
- inquisitor_mcp-0.1.0/.github/workflows/publish.yml +23 -0
- inquisitor_mcp-0.1.0/.gitignore +24 -0
- inquisitor_mcp-0.1.0/.mcp.json +8 -0
- inquisitor_mcp-0.1.0/AGENTS.md +40 -0
- inquisitor_mcp-0.1.0/LICENSE +21 -0
- inquisitor_mcp-0.1.0/PKG-INFO +337 -0
- inquisitor_mcp-0.1.0/README.md +309 -0
- inquisitor_mcp-0.1.0/docs/companion-skills.md +69 -0
- inquisitor_mcp-0.1.0/pyproject.toml +65 -0
- inquisitor_mcp-0.1.0/server.json +20 -0
- inquisitor_mcp-0.1.0/skills/inquisitor/CORE.md +49 -0
- inquisitor_mcp-0.1.0/skills/inquisitor/SKILL.md +228 -0
- inquisitor_mcp-0.1.0/src/inquisitor/__init__.py +3 -0
- inquisitor_mcp-0.1.0/src/inquisitor/backend/__init__.py +0 -0
- inquisitor_mcp-0.1.0/src/inquisitor/backend/analyzer.py +279 -0
- inquisitor_mcp-0.1.0/src/inquisitor/backend/extract.py +240 -0
- inquisitor_mcp-0.1.0/src/inquisitor/backend/phase_tracker.py +187 -0
- inquisitor_mcp-0.1.0/src/inquisitor/backend/search.py +241 -0
- inquisitor_mcp-0.1.0/src/inquisitor/backend/tracer.py +141 -0
- inquisitor_mcp-0.1.0/src/inquisitor/config.py +25 -0
- inquisitor_mcp-0.1.0/src/inquisitor/server.py +125 -0
- inquisitor_mcp-0.1.0/src/inquisitor/tools/__init__.py +0 -0
- inquisitor_mcp-0.1.0/src/inquisitor/tools/analyze.py +20 -0
- inquisitor_mcp-0.1.0/src/inquisitor/tools/phase.py +60 -0
- inquisitor_mcp-0.1.0/src/inquisitor/tools/scaffold.py +87 -0
- inquisitor_mcp-0.1.0/src/inquisitor/tools/search.py +61 -0
- inquisitor_mcp-0.1.0/src/inquisitor/tools/trace.py +34 -0
- inquisitor_mcp-0.1.0/src/inquisitor/tools/verify.py +34 -0
- inquisitor_mcp-0.1.0/tests/test_analyze.py +45 -0
- inquisitor_mcp-0.1.0/tests/test_extract.py +96 -0
- inquisitor_mcp-0.1.0/tests/test_phase.py +113 -0
- inquisitor_mcp-0.1.0/tests/test_search.py +66 -0
- inquisitor_mcp-0.1.0/tests/test_security.py +74 -0
- inquisitor_mcp-0.1.0/tests/test_smoke.py +28 -0
- inquisitor_mcp-0.1.0/tests/test_trace.py +42 -0
- inquisitor_mcp-0.1.0/uv.lock +3212 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "inquisitor",
|
|
3
|
+
"description": "Inquisitor — optimal-path problem solving for AI agents: the behavioral skill plus the inquisitor-mcp server.",
|
|
4
|
+
"owner": {
|
|
5
|
+
"name": "0x2fycy3",
|
|
6
|
+
"url": "https://github.com/0x2fycy3"
|
|
7
|
+
},
|
|
8
|
+
"plugins": [
|
|
9
|
+
{
|
|
10
|
+
"name": "inquisitor",
|
|
11
|
+
"source": ".",
|
|
12
|
+
"description": "Optimal-path problem solving skill + inquisitor-mcp server (web search, project analysis, code tracing, Newton 7-phase state machine).",
|
|
13
|
+
"license": "MIT"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "inquisitor",
|
|
3
|
+
"displayName": "Inquisitor",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Optimal-path problem solving for AI agents. Triage, prune ceremony, and apply Newton's Analysis-Synthesis method only at the depth the problem demands. Bundles the behavioral skill and the inquisitor-mcp server (web search, project analysis, code tracing, phase tracking).",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "0x2fycy3",
|
|
8
|
+
"url": "https://github.com/0x2fycy3"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/0x2fycy3/inquisitor",
|
|
11
|
+
"repository": "https://github.com/0x2fycy3/inquisitor",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": ["problem-solving", "investigation", "web-search", "mcp", "newton", "triage"]
|
|
14
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, develop]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v5
|
|
20
|
+
with:
|
|
21
|
+
enable-cache: true
|
|
22
|
+
|
|
23
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
24
|
+
run: uv python install ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: uv sync --all-extras --dev
|
|
28
|
+
|
|
29
|
+
- name: Lint (ruff)
|
|
30
|
+
run: uv run ruff check .
|
|
31
|
+
|
|
32
|
+
- name: Test (pytest)
|
|
33
|
+
run: uv run pytest tests/ -v
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build-and-publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment: pypi
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write # trusted publishing — no API token needed
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Install uv
|
|
17
|
+
uses: astral-sh/setup-uv@v5
|
|
18
|
+
|
|
19
|
+
- name: Build sdist and wheel
|
|
20
|
+
run: uv build
|
|
21
|
+
|
|
22
|
+
- name: Publish to PyPI
|
|
23
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
*.egg
|
|
9
|
+
|
|
10
|
+
# Inquisitor
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
*.db
|
|
13
|
+
|
|
14
|
+
# IDE
|
|
15
|
+
.vscode/
|
|
16
|
+
.idea/
|
|
17
|
+
|
|
18
|
+
# OS
|
|
19
|
+
.DS_Store
|
|
20
|
+
Thumbs.db
|
|
21
|
+
|
|
22
|
+
# reff — reference repos (not part of this project)
|
|
23
|
+
reff/
|
|
24
|
+
.firecrawl/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# AGENTS.md — Inquisitor (always-on)
|
|
2
|
+
|
|
3
|
+
Disciplined problem solving for AI agents: **estimate, prune, and spend your budget where the problem actually is.** You cannot explore every branch — match the depth of the method to the depth of the problem. Overcomplication is a failure mode, exactly like a wrong answer.
|
|
4
|
+
|
|
5
|
+
> This file is the always-on core. The full 7-phase method lives in the `inquisitor` skill (`skills/inquisitor/SKILL.md`), mandatory for COMPLEX problems. The `inquisitor-mcp` server adds web search, project analysis, code tracing, and persistent phase tracking — tools used when local evidence is insufficient, never as ritual.
|
|
6
|
+
|
|
7
|
+
## TRIAGE every problem (10 seconds)
|
|
8
|
+
|
|
9
|
+
| Class | Signal | Path |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| TRIVIAL | Obvious, local, one-liner | Fix → verify → done. No ceremony. |
|
|
12
|
+
| SIMPLE | Cause clear, single component | Success criteria → minimal evidence → fix → verify |
|
|
13
|
+
| COMPLEX | Root cause unknown, multi-component, or 2 failed fixes | Load the `inquisitor` skill: full 7-phase method + session tracking |
|
|
14
|
+
|
|
15
|
+
## Auto-escalate (objective — overrides how the problem "feels")
|
|
16
|
+
|
|
17
|
+
- Config/infra/deploy/routing/CI/hosting/DNS/env → min SIMPLE + loop-closure below
|
|
18
|
+
- Auth/security/secrets, data migrations/deletes/PII, concurrency → min COMPLEX
|
|
19
|
+
- Fix spans 2+ files → min SIMPLE. Prod-only symptom or unreachable runtime → COMPLEX.
|
|
20
|
+
- Failed attempt → up one class. Downgrades are never automatic.
|
|
21
|
+
|
|
22
|
+
## Confidence check (before committing to a class)
|
|
23
|
+
|
|
24
|
+
1. Read the actual runtime code path? 2. Can name the runtime signal proving the fix worked? 3. Verified the platform/tool assumption the fix depends on?
|
|
25
|
+
1 NO → min SIMPLE. 2+ NO → min COMPLEX. Certainty without verification is the bug.
|
|
26
|
+
|
|
27
|
+
## Before declaring done
|
|
28
|
+
|
|
29
|
+
- Name the runtime signal that proves the fix is live, and the smallest check that fails if it's a no-op. Can't name one → verify now or tell the user "I could not verify runtime; test X". Ship-if-unsure is banned.
|
|
30
|
+
- Hold ≥2 competing hypotheses while investigating; experiments discriminate, not confirm.
|
|
31
|
+
- Open queries route to a durable home, formatted `[OPEN] <question> — closes when: <check>`.
|
|
32
|
+
|
|
33
|
+
## Code (ponytail ladder — stop at first rung that holds)
|
|
34
|
+
|
|
35
|
+
1. Needs to exist? (YAGNI) 2. Already in codebase? 3. Stdlib? 4. Native platform? 5. Installed dep? 6. One line? 7. Minimum that works.
|
|
36
|
+
Root cause, not symptom: grep every caller, fix where all callers route through. Surgical diffs. Claims cite `file:line` or tool output.
|
|
37
|
+
|
|
38
|
+
## Shipping
|
|
39
|
+
|
|
40
|
+
NEVER commit/push/PR unless the user explicitly asked. Before any git operation, re-read workspace state in the SAME turn (`git branch --show-current`, `git status`). Match the repo's commit convention. Atomic commits. No secrets, no unrelated dirty files.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 inquisitor contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: inquisitor-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Optimal-path problem solving for AI agents — an MCP server for triage, web search, project analysis, code tracing, and Newton-method investigation.
|
|
5
|
+
Project-URL: Homepage, https://github.com/0x2fycy3/inquisitor
|
|
6
|
+
Project-URL: Repository, https://github.com/0x2fycy3/inquisitor
|
|
7
|
+
Project-URL: Issues, https://github.com/0x2fycy3/inquisitor/issues
|
|
8
|
+
Author: 0x2fycy3
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-agents,claude,developer-tools,llm,mcp,model-context-protocol,problem-solving,web-search
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Requires-Dist: ddgs>=9.0.0
|
|
20
|
+
Requires-Dist: httpx>=0.27.0
|
|
21
|
+
Requires-Dist: mcp>=1.0.0
|
|
22
|
+
Requires-Dist: pypdf>=5.0.0
|
|
23
|
+
Requires-Dist: readability-lxml>=0.8.0
|
|
24
|
+
Requires-Dist: trafilatura>=2.0.0
|
|
25
|
+
Provides-Extra: docling
|
|
26
|
+
Requires-Dist: docling>=2.0.0; extra == 'docling'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
<div align="center">
|
|
30
|
+
|
|
31
|
+
# inquisitor
|
|
32
|
+
|
|
33
|
+
**Optimal-path problem solving for AI agents**
|
|
34
|
+
Triage · Prune · Investigate — never overcomplicate
|
|
35
|
+
|
|
36
|
+
[](https://python.org)
|
|
37
|
+
[](https://modelcontextprotocol.io)
|
|
38
|
+
[](https://github.com/astral-sh/uv)
|
|
39
|
+
[](https://github.com/0x2fycy3/inquisitor/actions/workflows/ci.yml)
|
|
40
|
+
[]()
|
|
41
|
+
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<!-- mcp-name: io.github.0x2fycy3/inquisitor -->
|
|
45
|
+
|
|
46
|
+
## Overview
|
|
47
|
+
|
|
48
|
+
**inquisitor** makes AI agents solve problems the way a chess engine plays chess: it cannot explore every branch, so it **estimates complexity first, prunes paths that add no information, and spends its search budget only where the problem actually is**.
|
|
49
|
+
|
|
50
|
+
It ships as two coordinated layers:
|
|
51
|
+
|
|
52
|
+
- **MCP server** (`inquisitor-mcp`) — the engine. Web search, project analysis, code tracing, project scaffolding, and a persistent investigation state machine. Works with any MCP-compatible agent: OpenCode, Claude Code, Claude Desktop, Cursor.
|
|
53
|
+
- **Agent skill** (`skills/inquisitor/SKILL.md`) — the behavioral layer. Injects the triage heuristic, the pruning rules, and the full methodology into the agent's reasoning.
|
|
54
|
+
|
|
55
|
+
The methodology synthesizes four sources:
|
|
56
|
+
|
|
57
|
+
| Source | Contribution |
|
|
58
|
+
|--------|--------------|
|
|
59
|
+
| Newton's *Opticks* (1704) | Analysis→Synthesis method: define, decompose, experiment, reconstruct, and end with open Queries — *hypotheses non fingo* |
|
|
60
|
+
| NASA/JPL *Power of Ten* | 10 hard rules, few enough to remember, strict enough to check mechanically |
|
|
61
|
+
| Karpathy's LLM coding guidelines | Think before coding · simplicity first · surgical changes · goal-driven execution |
|
|
62
|
+
| Ponytail decision ladder | YAGNI → reuse → stdlib → native → installed dep → one line → minimum code |
|
|
63
|
+
|
|
64
|
+
> Web search, codebase scans, and code tracing are **tools invoked when local evidence is insufficient — never mandatory rituals**.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## How it decides
|
|
69
|
+
|
|
70
|
+
Every problem goes through 10-second triage before anything else:
|
|
71
|
+
|
|
72
|
+
```mermaid
|
|
73
|
+
flowchart TD
|
|
74
|
+
P([Problem]) --> T{"TRIAGE<br/>10-second<br/>complexity estimate"}
|
|
75
|
+
T -->|"obvious, local"| TR["<b>TRIVIAL</b>"]
|
|
76
|
+
T -->|"cause clear,<br/>single component"| SI["<b>SIMPLE</b>"]
|
|
77
|
+
T -->|"root cause unknown,<br/>multi-component"| CO["<b>COMPLEX</b>"]
|
|
78
|
+
|
|
79
|
+
TR --> TRp["fix → verify<br/><i>no ceremony</i>"]
|
|
80
|
+
SI --> SIp["success criteria → minimal<br/>evidence → fix → verify"]
|
|
81
|
+
CO --> COp["Newton 7-phase:<br/>DEFINE → AXIOMS → ANALYSIS →<br/>EXPERIMENT → SYNTHESIS →<br/>VALIDATE → QUERY<br/><i>+ session tracking as memory</i>"]
|
|
82
|
+
|
|
83
|
+
TR -.->|"objective trigger /<br/>failed fix / low confidence"| SI
|
|
84
|
+
SI -.->|"escalate — never downgrade"| CO
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Escalation is enforced, not just allowed.** The subjective estimate is only a starting point: objective triggers (touching infra/deploy/routing/config, auth/security, data migrations, multi-file fixes, prod-only symptoms) force a minimum class regardless of how "clear" the problem feels, and a 3-question confidence check (read the runtime path? can name the runtime signal? verified the platform assumption?) bumps the class up per unanswered question. Downgrades are never automatic. **Inflated ceremony is not allowed either** — a 7-phase investigation of a typo is as wrong as a blind guess at a race condition.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Installation
|
|
92
|
+
|
|
93
|
+
Requires [uv](https://github.com/astral-sh/uv) and Python 3.12+.
|
|
94
|
+
|
|
95
|
+
### Claude Code — plugin install (recommended)
|
|
96
|
+
|
|
97
|
+
inquisitor ships as a [Claude Code plugin](https://code.claude.com/docs/en/plugins) that installs **both the skill and the MCP server** — no cloning, no editing absolute paths, no manual symlink.
|
|
98
|
+
|
|
99
|
+
From within Claude Code, first add the marketplace:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
/plugin marketplace add 0x2fycy3/inquisitor
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Then install the plugin:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
/plugin install inquisitor@inquisitor
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
That's it. The plugin bundles the `inquisitor-mcp` server (registered automatically via `${CLAUDE_PLUGIN_ROOT}`) and the `inquisitor` skill. `uv` syncs the server's dependencies on first launch. Update later with `/plugin marketplace update inquisitor`.
|
|
112
|
+
|
|
113
|
+
> Prefer to point at a local checkout instead of GitHub? `/plugin marketplace add /path/to/inquisitor` works too.
|
|
114
|
+
|
|
115
|
+
For **OpenCode** and **Claude Desktop** (which don't use Claude Code plugins), or for a manual Claude Code setup, use the steps below.
|
|
116
|
+
|
|
117
|
+
### Step 1 — Get the server
|
|
118
|
+
|
|
119
|
+
**Option A — no clone (recommended).** Once published to PyPI, `uvx` fetches and runs it on demand — no clone, no absolute paths:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
uvx inquisitor-mcp # prints a ready message and waits for a client — Ctrl+C to exit
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
You'll reference `uvx inquisitor-mcp` directly in the config below.
|
|
126
|
+
|
|
127
|
+
**Option B — from a checkout** (for local development, or before the PyPI release):
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git clone https://github.com/0x2fycy3/inquisitor.git ~/tools/inquisitor
|
|
131
|
+
cd ~/tools/inquisitor
|
|
132
|
+
uv sync
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
> The clone path is up to you — just use the **same absolute path** in the config below. `~` does not expand inside JSON config files, so write the full path (e.g. `/home/you/tools/inquisitor`).
|
|
136
|
+
|
|
137
|
+
You do **not** run the server manually. It's a stdio MCP server: your agent spawns and manages it automatically. (If you run it by hand it prints a ready message on stderr and waits silently — that's normal.)
|
|
138
|
+
|
|
139
|
+
### Step 2 — Register the MCP server with your agent
|
|
140
|
+
|
|
141
|
+
**OpenCode** — add to `~/.config/opencode/opencode.json` (global) or `./opencode.json` (per-project):
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"$schema": "https://opencode.ai/config.json",
|
|
146
|
+
"mcp": {
|
|
147
|
+
"inquisitor": {
|
|
148
|
+
"type": "local",
|
|
149
|
+
"command": ["uvx", "inquisitor-mcp"],
|
|
150
|
+
"enabled": true
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Claude Code** — add to `.mcp.json` in your project, or `~/.claude.json` for all projects:
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"mcpServers": {
|
|
161
|
+
"inquisitor": {
|
|
162
|
+
"command": "uvx",
|
|
163
|
+
"args": ["inquisitor-mcp"]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Claude Desktop** — same `mcpServers` block in `claude_desktop_config.json` (Settings → Developer → Edit Config).
|
|
170
|
+
|
|
171
|
+
> Using a checkout instead of `uvx`? Swap the command for `uv` with args `["run", "--directory", "/home/you/tools/inquisitor", "inquisitor-mcp"]`.
|
|
172
|
+
|
|
173
|
+
### Step 3 — Install the skill (the behavioral layer)
|
|
174
|
+
|
|
175
|
+
Symlink it so it stays up to date with the repo:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# OpenCode
|
|
179
|
+
mkdir -p ~/.config/opencode/skills
|
|
180
|
+
ln -s /home/you/tools/inquisitor/skills/inquisitor ~/.config/opencode/skills/inquisitor
|
|
181
|
+
|
|
182
|
+
# Claude Code
|
|
183
|
+
mkdir -p ~/.claude/skills
|
|
184
|
+
ln -s /home/you/tools/inquisitor/skills/inquisitor ~/.claude/skills/inquisitor
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
(Copying the folder works too — you'll just need to re-copy after updates.)
|
|
188
|
+
|
|
189
|
+
### Step 4 — Restart your agent
|
|
190
|
+
|
|
191
|
+
Config is loaded at startup. Quit and reopen OpenCode / Claude Code, then verify:
|
|
192
|
+
the `inquisitor_*` tools appear in the tool list, and the `inquisitor` skill is available.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Tools
|
|
197
|
+
|
|
198
|
+
| Tool | Purpose | When |
|
|
199
|
+
|------|---------|------|
|
|
200
|
+
| `inquisitor_search` | Multi-backend web search (DuckDuckGo free/keyless, Brave, SearXNG) with content extraction (HTML + PDF) | Local evidence insufficient: unknown errors, unfamiliar libraries, current best practices |
|
|
201
|
+
| `inquisitor_analyze` | Project overview: languages, frameworks, tests, deps, git history | Entering an unfamiliar codebase |
|
|
202
|
+
| `inquisitor_trace` | Symbol tracing: definition, callers, callees with `file:line` refs | Bug spans multiple functions/files |
|
|
203
|
+
| `inquisitor_phase_get` / `_set` | Newton 7-phase state machine, SQLite-backed per project | COMPLEX investigations — persistent memory across turns |
|
|
204
|
+
| `inquisitor_verify` | Validates findings: evidence cited? phases complete? contradictions? | Before declaring a COMPLEX investigation done |
|
|
205
|
+
| `inquisitor_scaffold` | Minimal project scaffolding with researched best practices | New project setup, after requirements are clarified |
|
|
206
|
+
|
|
207
|
+
### Example: `inquisitor_search`
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
inquisitor_search(
|
|
211
|
+
query="httpx ConnectTimeout retry pattern",
|
|
212
|
+
max_results=8,
|
|
213
|
+
time_range="year", # day | week | month | year
|
|
214
|
+
include_domains=["github.com"], # optional site: filter
|
|
215
|
+
fetch_content=True, # full page text, not just snippets
|
|
216
|
+
)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Example: phase tracking (COMPLEX path)
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
inquisitor_phase_set(
|
|
223
|
+
target_phase="experiment",
|
|
224
|
+
findings="500 only occurs when session token > 4KB",
|
|
225
|
+
evidence="repro script output; nginx.conf:34 large_client_header_buffers",
|
|
226
|
+
open_questions="why did token size grow after v2.3 deploy?",
|
|
227
|
+
)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Project Structure
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
inquisitor/
|
|
236
|
+
├── src/inquisitor/
|
|
237
|
+
│ ├── server.py # MCP entry point (FastMCP, 6 tools)
|
|
238
|
+
│ ├── config.py # env configuration
|
|
239
|
+
│ ├── tools/ # thin MCP adapters
|
|
240
|
+
│ │ └── search / analyze / trace / scaffold / phase / verify
|
|
241
|
+
│ └── backend/ # pure Python, zero MCP dependency
|
|
242
|
+
│ ├── search.py # DDG / Brave / SearXNG + re-ranking
|
|
243
|
+
│ ├── extract.py # trafilatura → readability fallback, SSRF guard
|
|
244
|
+
│ ├── analyzer.py # project structure scan
|
|
245
|
+
│ ├── tracer.py # callers / callees mapping
|
|
246
|
+
│ └── phase_tracker.py # Newton state machine (SQLite)
|
|
247
|
+
├── skills/inquisitor/SKILL.md # behavioral layer for the agent
|
|
248
|
+
├── .claude-plugin/
|
|
249
|
+
│ ├── plugin.json # Claude Code plugin manifest
|
|
250
|
+
│ └── marketplace.json # self-hosted marketplace (source ".")
|
|
251
|
+
├── .mcp.json # bundled MCP server (${CLAUDE_PLUGIN_ROOT})
|
|
252
|
+
└── tests/ # 36 tests
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The `backend/` package is importable standalone — no MCP required:
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
from inquisitor.backend.search import search
|
|
259
|
+
results = search("python asyncio best practices", max_results=5)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Environment Variables
|
|
265
|
+
|
|
266
|
+
| Variable | Required | Default | Description |
|
|
267
|
+
|----------|----------|---------|-------------|
|
|
268
|
+
| `INQUISITOR_SESSION_DIR` | no | `~/.inquisitor/sessions/` | Investigation state storage |
|
|
269
|
+
| `BRAVE_API_KEY` | no | — | Brave Search backend (2k free/month) |
|
|
270
|
+
| `SEARXNG_URL` | no | — | Self-hosted SearXNG instance |
|
|
271
|
+
| `INQUISITOR_DEFAULT_ENGINE` | no | `ddg` | `ddg` \| `brave` \| `searxng` |
|
|
272
|
+
| `INQUISITOR_SEARCH_TIMEOUT` | no | `15` | HTTP timeout (seconds) |
|
|
273
|
+
| `INQUISITOR_MAX_CONTENT_LENGTH` | no | `40000` | Max chars per fetched page |
|
|
274
|
+
| `INQUISITOR_PREFERRED_DOMAINS` | no | — | Comma-separated domains to boost in ranking |
|
|
275
|
+
| `INQUISITOR_PDF_BACKEND` | no | `auto` | PDF extraction: `auto` \| `docling` \| `pypdf` |
|
|
276
|
+
|
|
277
|
+
No API key is required — DuckDuckGo works out of the box.
|
|
278
|
+
|
|
279
|
+
### PDF extraction
|
|
280
|
+
|
|
281
|
+
Search results and fetched URLs that are PDFs (RFCs, specs, papers, datasheets) are extracted, not skipped. The default policy is `auto`, which uses **pypdf** (pure-Python, fast, no models, handles text PDFs) unless docling is installed and a GPU is present.
|
|
282
|
+
For complex tables or scanned/OCR PDFs, install the optional **docling** backend:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
uv pip install "inquisitor-mcp[docling]" # or: pip install "inquisitor-mcp[docling]"
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
docling is heavy (pulls in `torch` + ML models) and slow on CPU, so `auto` only uses it when it's installed **and** a GPU is present; otherwise it falls back to pypdf. Force it with `INQUISITOR_PDF_BACKEND=docling` (works on CPU, just slower), or pin pypdf with `INQUISITOR_PDF_BACKEND=pypdf`. Any docling failure falls back to pypdf, so a PDF read never hard-fails.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Security
|
|
293
|
+
|
|
294
|
+
- **SSRF guard**: content fetching refuses non-http(s) schemes and loopback / private / link-local / metadata targets (`localhost`, `127.0.0.1`, `10.x`, `192.168.x`, `169.254.169.254`, …).
|
|
295
|
+
- **Path traversal guard**: session names are sanitized before touching the filesystem.
|
|
296
|
+
- **No shell execution**: subprocess calls use argument lists, never `shell=True`.
|
|
297
|
+
- **Parameterized SQL** throughout the session store.
|
|
298
|
+
- The server runs locally over stdio with your user's privileges — it does not listen on the network.
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Companion skills
|
|
303
|
+
|
|
304
|
+
inquisitor is a router as much as an investigator — it delegates to purpose-built skills (`/tdd`, `/code-review`, …) when one fits, but it never installs them for you. See **[docs/companion-skills.md](docs/companion-skills.md)** for the curated set worth installing alongside it (mattpocock/skills, spec-kit, last30days, ponytail, gstack) and design references.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Development
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
uv sync # install deps
|
|
312
|
+
uv run pytest tests/ -v # run tests
|
|
313
|
+
uv run ruff check . # lint
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Tech
|
|
317
|
+
|
|
318
|
+
- **uv** — package manager
|
|
319
|
+
- **FastMCP** — MCP server framework
|
|
320
|
+
- **ddgs / httpx** — search + HTTP
|
|
321
|
+
- **trafilatura + readability-lxml** — content extraction (two-tier fallback)
|
|
322
|
+
- **SQLite** — investigation state
|
|
323
|
+
- **pytest / ruff** — tests and lint
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Acknowledgments
|
|
328
|
+
|
|
329
|
+
The methodology and architecture stand on these shoulders:
|
|
330
|
+
|
|
331
|
+
- **Sir Isaac Newton — [*Opticks* (1704)](https://www.gutenberg.org/ebooks/33504)** — the Analysis→Synthesis method and the closing Queries pattern. Public domain via Project Gutenberg.
|
|
332
|
+
- **Gerard J. Holzmann (NASA/JPL) — [*The Power of Ten: Rules for Developing Safety Critical Code*](https://spinroot.com/gerard/pdf/P10.pdf)** — the template for a rule set small enough to remember and strict enough to check mechanically.
|
|
333
|
+
- **[andrej-karpathy-skills](https://github.com/forrestchang/andrej-karpathy-skills)** (forrestchang) — behavioral guidelines derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls.
|
|
334
|
+
- **[ponytail](https://github.com/dietrichgebert/ponytail)** (Dietrich Gebert) — the decision ladder and the lazy-senior-dev discipline.
|
|
335
|
+
- **[last30days-skill](https://github.com/mvanhorn/last30days-skill)** (mvanhorn) — inspiration for multi-source research design and the SKILL.md-as-contract pattern.
|
|
336
|
+
|
|
337
|
+
Licensed under [MIT](LICENSE).
|