Skip to content

feat(mcp): expose dvalin_scan so any agent can call the scanner - #161

Merged
arthurpanhku merged 2 commits into
mainfrom
feat/mcp-scan-tool
Aug 8, 2026
Merged

feat(mcp): expose dvalin_scan so any agent can call the scanner#161
arthurpanhku merged 2 commits into
mainfrom
feat/mcp-scan-tool

Conversation

@arthurpanhku

Copy link
Copy Markdown
Owner

Summary

If an agent writes the code, something other than that agent has to check it. That is the same governance argument this project already makes, applied to who is actually writing code now — and the MCP server was not set up for it.

All three existing tools were heavyweight. dvalin_run_task asks a calling agent to hand over an entire coding task, which needs DvalinCode's own provider configured and a lot of trust. Nothing let an agent do the cheap, obvious thing: check what it just wrote.

dvalin_scan is read-only and deterministic — no model, no credentials, no edits. That property matters more for an agent than for a person: it does not stack another layer of nondeterminism on top of the caller's own. It is listed first and defaults to the builtin engine, so the default call works on a machine with nothing installed.

Designed for a caller with a context window

  • Trimmed by default. The per-finding repair prompt and source snippet are ~1KB each; an agent that wants context can read the file itself. include_remediation_prompts opts back in.
  • Capped at 50 findings, with the true total reported, so one scan on a large repo cannot flood the caller.
  • Measured: ~170ms including process start, ~600 byte payload for a single finding.

Testing

Verified end to end over real stdio MCP against a vulnerable fixture — full initializetools/call handshake with a separate client process, correct file and line reported.

10 unit tests cover the default scanner set, trimming, the cap and limit, unknown-scanner rejection, the workspace guard refusing a path outside --workspace, timeout conversion to milliseconds, and the missing-engine report.

The existing "exactly the three task-level tools" test is updated, not loosened — it exists to pin the surface, so it now pins four and asserts each tool's readOnlyHint by name.

npm run check green at 332 tests / 50 files. Repo self-scan clean.

Also in this PR (second commit)

  • README section in both languages.
  • integrations/claude-code/ — MCP setup snippet plus a Claude Code skill. The skill falls back to npx -y dvalincode when no MCP server is configured, so it works with nothing installed. It also states what a scan does not prove, which matters more than the invocation: a clean scan is not a safety certificate, and suppressing a finding to make it pass is not a fix.
  • server.json — the MCP registry manifest.
  • integrations/README.md separates the two unrelated things called "skills" here: DvalinCode's JSON bundles, and Anthropic's SKILL.md directories.

Every flag documented was checked against mcp-serve --help, not written from memory.

Security and AI Governance

  • This change does not expand file, shell, network, model, or approval permissions.
  • If it changes agent behavior, prompts, policy, providers, audit logging, or release/build security, I updated the relevant governance evidence in docs/.
  • If it introduces a new model/provider/tool or new data flow, I completed docs/governance/AI-CHANGE-IMPACT-ASSESSMENT.md.

Third box unticked, but this is the one where a reviewer should push back hardest if they disagree — it does add a new agent-facing tool:

  • dvalin_scan is strictly narrower than what the server already exposed. It runs no model, resolves no provider, and cannot write; dvalin_run_task beside it can do all three. It goes through the same resolveAllowedWorkspace guard, so --workspace still bounds it.
  • No new egress: the builtin scanner is local. The optional engines may fetch rule databases, exactly as they already do from the CLI and under the same command policy.

I did not fill out the assessment because the template covers agent permissions, prompts, provider handling, audit, and release security, and this touches none — but the call is yours.

Notes

Not done, needs your decision: submitting to the MCP registry and to awesome-mcp-servers. Both mean opening a pull request on someone else's repository under your identity, so I prepared server.json and stopped there. Say the word and I will draft both submissions.

.dvalincodeignore did not grow. The self-scan flagged this PR's own test file, on a mock snippet value. Unlike the three fixtures already excluded, that value is not load-bearing — the test only asserts the field is absent — so it became a neutral placeholder instead of a fifth exclusion. The exclusion list is supposed to stay surgical; this was a case where the vulnerable pattern was not actually the fixture.

arthurpanhku and others added 2 commits August 8, 2026 09:55
The MCP surface repeated the mistake the README made: all three tools were
heavyweight. `dvalin_run_task` asks a calling agent to hand over an entire
coding task, which needs DvalinCode's own provider configured and a lot of
trust. Nothing let an agent do the cheap, obvious thing — check the code it
just wrote.

`dvalin_scan` is read-only and deterministic: no model, no credentials, no
edits. That matters more for an agent than for a person, because it does
not stack another layer of nondeterminism on top of the caller's own. It is
listed first, and defaults to the `builtin` engine so the default call
works on a machine with nothing installed.

Findings are trimmed by default — the per-finding repair prompt and source
snippet are ~1KB each, and an agent that wants context can read the file.
`include_remediation_prompts` opts back in. Results are capped at 50 with
the true total reported, so one scan cannot flood a caller's context.

Verified end to end over real stdio MCP against a vulnerable fixture:
~170ms including process start, ~600 byte payload, correct file and line.
10 unit tests cover the default scanner set, trimming, the cap, unknown
scanner rejection, the workspace guard, and timeout conversion.

The existing test asserting "exactly the three task-level tools" is updated
rather than loosened — it exists to pin the surface, so it now pins four
and asserts each tool's readOnly annotation by name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds the pieces that make the MCP server findable and usable:

- A README section in both languages: if an agent writes the code,
  something other than that agent has to check it.
- integrations/claude-code/ — an MCP setup snippet and a Claude Code skill.
  The skill falls back to `npx -y dvalincode` when no MCP server is
  configured, so it works with nothing installed. It also tells Claude what
  a scan does *not* prove, which matters more than the invocation: a clean
  scan is not a safety certificate, and suppressing a finding to make it
  pass is not a fix.
- server.json — the MCP registry manifest, so the server can be listed
  rather than only documented.

integrations/README.md separates the two unrelated things called "skills"
in this project: DvalinCode's own JSON bundles under ~/.dvalincode/skills,
and Anthropic's SKILL.md directories that Claude Code loads.

Every flag documented here was checked against `mcp-serve --help` rather
than written from memory.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@arthurpanhku
arthurpanhku merged commit af0011e into main Aug 8, 2026
13 checks passed
@arthurpanhku
arthurpanhku deleted the feat/mcp-scan-tool branch August 8, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant