Skip to main content
Glama
LSDubose

grc-evidence-mcp

by LSDubose

grc-evidence-mcp — Step-by-Step Build Guide

Build a real, read-only GRC evidence-collection MCP in Python, connect it to Claude Desktop, test it against your own GitHub repository, and optionally add visual evidence capture with Playwright.

This guide is written so you can complete the build even if you have never built an MCP before. If you are already comfortable with Python, terminals, APIs, or Claude Code, you can move faster and use the explanations only when you need them.

Finished repo: [GITHUB REPO LINK]

What you are building

By the end, your MCP will be able to:

  1. List the evidence sources it knows about.

  2. Collect real GitHub evidence for branch protection and CODEOWNERS.

  3. Map that evidence to control references.

  4. Store the full evidence locally in SQLite and return only an opaque collection_id to Claude.

  5. Retrieve a stored evidence collection by its id.

  6. Optionally capture a real webpage screenshot with Playwright and store it as visual evidence.

The design rule for the whole project is simple: read evidence FROM the audited system; write evidence only TO your local landing zone. Never modify the audited system.


Choose your pace

You can build this in one sitting by following the guide from top to bottom, or spread it over five days.

Related MCP server: Change Trace MCP

5-day path

Day 1 — Set up Claude Code and build the foundation

Goal: Get a working MCP project with local evidence storage and one visible tool.

Actions:

  • Install Claude Code.

  • Create an empty project folder.

  • Start Claude Code inside the folder.

  • Paste Prompt 1.

  • Let Claude Code create the Python project, SQLite-backed StateStore, and list_evidence_sources tool.

  • Run the project locally and resolve any install errors before moving on.

Done when: Claude Code can run the MCP and list_evidence_sources exists.

Day 2 — Connect the MCP to Claude Desktop

Goal: Make Claude Desktop see the MCP you built.

Actions:

  • Paste Prompt 2 into Claude Code.

  • Let Claude Code update the Claude Desktop MCP configuration using the full server path.

  • Fully quit Claude Desktop and reopen it.

  • Open a new chat and check the tools/hammer icon.

Done when: list_evidence_sources appears as a tool in Claude Desktop.

Day 3 — Add the real GitHub evidence source

Goal: Replace “demo-only” thinking with a real read-only API call.

Actions:

  • Paste Prompt 3.

  • Create a fine-grained GitHub personal access token with only the permissions required by this build.

  • Copy .env.example to .env and add the token there.

  • Never paste the token itself into Claude Desktop or Claude Code chat.

  • Restart Claude Desktop after the environment/config changes.

Done when: the MCP has a working collect_evidence tool and your token is available to the server.

Day 4 — Test, retrieve, and inspect real evidence

Goal: Prove your MCP works against a repository you actually control.

Actions:

  • Run the GitHub test prompt against your own repository.

  • Copy the returned collection_id.

  • Ask Claude Desktop to retrieve that collection.

  • Review the branch-protection and CODEOWNERS findings.

  • Read the 404 limitation section before treating an “absent” result as a control gap.

Done when: you have retrieved a stored record produced by a live GitHub API call.

Day 5 — Add visual evidence, clean up, and publish

Goal: Turn the project into something portfolio-ready.

Actions:

  • Install the optional Playwright extra and Chromium.

  • Add or verify collect_visual_evidence.

  • Capture a screenshot of a real page you are authorized to access.

  • Retrieve the screenshot evidence collection and inspect its metadata.

  • Clean up your README, confirm .env is ignored, and push the project to GitHub.

  • If you are entering the challenge, submit your repo using the challenge instructions.

Done when: your repository explains what the MCP does, how to run it, what its limitations are, and includes no secrets.


Before you start

You need:

  • A computer with a terminal.

  • A Claude account that can use Claude Code.

  • Claude Desktop for the desktop-tool portion of the walkthrough.

  • GitHub account access and at least one repository you are allowed to test.

  • Python 3.10 or newer.

  • Node.js if your machine does not already have it.

If you are brand new

You do not need to understand every line of Python before you begin. Your job during this build is to understand what each component is responsible for, what data enters it, what comes back, and where the security boundaries are. When Claude Code creates or changes a file, ask it to explain the file in plain English before moving on if you are unsure.

If you are more technical

You can inspect the generated files, run tests between each prompt, and challenge Claude Code on implementation choices. The finished repo is a reference implementation, not a requirement that every file look identical.


Step 1 — Install Claude Code

Run:

npm install -g @anthropic-ai/claude-code

If that errors because Node.js is missing, install Node.js, then run the command again.

Start Claude Code:

claude

The first run will ask you to sign in.

This build is intentionally terminal-first. You do not need a separate editor to complete it.


Step 2 — Create your project folder

mkdir my-evidence-mcp
cd my-evidence-mcp
claude

From this point forward, paste the build prompts into Claude Code in order.


Prompt 1 — Build the foundation

Help me build a small MCP server in Python called grc-evidence-mcp, using
FastMCP over stdio, that I'll connect to Claude Desktop.

Purpose: read-only compliance evidence collection. It reads evidence FROM
systems and writes evidence TO a local landing zone — it must never modify
the audited system itself.

Build the foundation first, not real sources yet:

1. A StateStore class backed by SQLite — save(record) returns an opaque id,
   get(id) returns the record back. That id is the only handle anything
   else gets to a stored record.
2. One tool: list_evidence_sources — returns available sources and flags
   which ones are just stubs for now. Register one stub source so the
   list isn't empty.

Get this running and visible as a tool in Claude Code before we add
anything real.

What this step is teaching you

The StateStore separates the conversation from the full evidence record. Instead of handing all collected evidence directly back to the model, the server stores it locally and gives Claude an id. Claude can pass that id back later without having to reproduce the evidence itself.

Checkpoint

Before moving on, ask Claude Code to show you:

  • where the MCP server starts,

  • where StateStore writes data,

  • where list_evidence_sources is registered,

  • and the command it used to confirm the server starts successfully.


Prompt 2 — Connect it to Claude Desktop

Add this server to my Claude Desktop config at ~/Library/Application
Support/Claude/claude_desktop_config.json. Use the full path to the
server, not just the command name, so it doesn't rely on my terminal's
PATH.

This path is the macOS path used in the walkthrough. If you are on another operating system, ask Claude Code to locate the Claude Desktop MCP configuration file for your operating system before it edits anything.

Use the full path to the server command. Claude Desktop does not necessarily inherit the same PATH as your terminal.

Then fully quit Claude Desktop and reopen it. A normal window close or reload may not reload the MCP configuration.

Open a new chat and check the tools/hammer icon. You should see list_evidence_sources.

If you do not see the tool

Check these in order:

  1. Did Claude Code save the config to the correct Claude Desktop config file?

  2. Does the config use a full executable/server path?

  3. Does the MCP start successfully from your terminal?

  4. Did you fully quit and reopen Claude Desktop?

  5. Did you open a new chat after restarting?

Do not continue to the GitHub step until the foundation tool is visible.


Prompt 3 — Add the real GitHub source

Now build the first real source: GitHub.

Add a collect_evidence(source_name, params) tool that, for source_name=
"github", checks branch protection status and CODEOWNERS presence on a
repo I specify (owner/repo/branch), using my own GitHub token
(read-only — Administration:read and Contents:read, nothing else).

Map each result to a control reference:
- branch protection present → SOC2-CC8.1, ISO27001-A.8.32
- CODEOWNERS present → SOC2-CC8.1, ISO27001-A.5.3

Return a collection_id from StateStore, not the raw evidence directly.
I want to run this against a real repo of mine and see actual results,
not sample data.

Create the GitHub token

Create a fine-grained personal access token for the repository you plan to test. Grant only:

  • Administration: read

  • Contents: read

Do not reuse a broader token just because you already have one.

Put the token in .env

The finished repo includes .env.example. Copy it:

cp .env.example .env

Then set:

GITHUB_TOKEN=your_token_value_here

The finished repo loads this .env file when the GitHub collector starts.

Never paste the actual token into a Claude Desktop or Claude Code message. The token belongs in the environment, not in the conversation. Also keep .env in .gitignore so it is never committed.

After changing the token/environment, fully restart Claude Desktop.


Step 4 — Test against your own repository

In Claude Desktop, ask:

Check branch protection and CODEOWNERS on [your-username]/[your-repo],
branch main.

This should make a real GitHub API call against the repository you named.

The tool should return a collection_id, not the full raw record.

Then ask:

Get the evidence collection with id [collection_id].

You should now see the stored evidence record.

What to inspect

Look for:

  • repository and branch name,

  • branch protection result,

  • CODEOWNERS result,

  • mapped control references,

  • underlying evidence/status details,

  • collection timestamp.

This is the point where the project becomes more than a demo: you have collected and retrieved evidence from a real system you control.


Important limitation — GitHub 404s are ambiguous

GitHub may return a 404 when branch protection is not configured, but a 404 can also occur because the repository/branch cannot be found or the caller does not have enough access to confirm the setting.

The current GitHub collector preserves the response details, but it still records a 404 result as present: false. Do not automatically treat that as a confirmed control gap. A human reviewer should verify whether the result means “not configured” or “could not confirm.”

That distinction is part of good GRC engineering: “no” and “I don’t know” are not the same finding.


Bonus — Add visual evidence with Playwright

This is optional. The core MCP works without it.

The finished repo uses Playwright with headless Chromium. It does not depend on the Claude for Chrome extension.

Install the optional package and browser:

pip install -e ".[screenshot]"
playwright install chromium

If you are building from prompts, use:

Add a tool collect_visual_evidence(url, subject) that opens the given URL
in headless Chromium via Playwright, captures a full-page screenshot, and
stores it the same way collect_evidence does — save the result to
StateStore, return only a collection_id, never the raw image bytes.

Classify the result conservatively: a successful page load can be stored
as present; a 401/403 authentication wall, a 404, or a navigation failure
must not be treated as proof that a control is missing. Record those as
indeterminate or error as appropriate. Burn a timestamp using the local
machine timezone into the screenshot metadata so a reviewer knows when
it was captured.

Then try:

Capture visual evidence of https://github.com/[your-username]/[your-repo]/settings/branches.

The screenshot tool stores the PNG under the MCP's local screenshots directory and stores its metadata in StateStore. It returns a new collection_id for that screenshot evidence record.

A screenshot shows what the page looked like at capture time. It is not proof by itself that a control is effective. The implementation intentionally treats authentication walls and 404s as indeterminate rather than control failures. The visual capture is page-specific and does not take a screenshot of your local desktop.


What the finished repo contains

  • grc_evidence_mcp/store.py — SQLite-backed StateStore with opaque ids.

  • grc_evidence_mcp/server.py — MCP tool registration and evidence-storage workflow.

  • grc_evidence_mcp/github.py — read-only GitHub API evidence collector.

  • grc_evidence_mcp/screenshot.py — optional Playwright screenshot collector.

  • .env.example — safe template for the GitHub token variable.

  • .gitignore — prevents local secrets such as .env from being committed.

  • pyproject.toml — Python dependencies and optional screenshot extra.

Core tools:

  • list_evidence_sources

  • collect_evidence

  • get_evidence_collection

Optional bonus tool:

  • collect_visual_evidence


Troubleshooting by symptom

claude command not found

Install Node.js if needed, then rerun the Claude Code npm install.

MCP tool does not appear in Claude Desktop

Verify the config location and full server path, confirm the server starts in the terminal, fully restart Claude Desktop, then open a new chat.

GITHUB_TOKEN is not set

Confirm .env exists in the project root, contains GITHUB_TOKEN=..., and you are running the updated project that loads .env. Restart Claude Desktop after changing environment/configuration.

GitHub returns 401

The token is invalid, expired, or not being read correctly.

GitHub returns 403

The token/account likely does not have the required read access to the repository or settings.

GitHub returns 404

Do not immediately call it a control failure. Confirm the repository, branch, token access, and the underlying GitHub response.

Playwright is not installed

Run:

pip install -e ".[screenshot]"
playwright install chromium

Screenshot shows a login page

That is still a real screenshot, but it does not prove the control state. Treat it as indeterminate and authenticate appropriately before trying again if you are authorized to do so.


Before you publish your repo

  • Make sure .env is not committed.

  • Search the repo for your token or other secrets.

  • Keep the README's limitation section.

  • Explain that the GitHub calls are read-only.

  • Explain that screenshots show page state at capture time, not control effectiveness.

  • Include enough setup instructions that another person could reproduce the build.

  • Use your own repository in screenshots/examples, or redact anything you should not publish.


For the challenge

To celebrate hitting 100 subscribers: a $306 giveaway — one year of Claude Pro plus one year of GRC Engineering Club membership.

To enter:

  1. Be subscribed.

  2. Build the MCP.

  3. Submit the GitHub repository for what you built.

One winner will be selected by random draw from qualifying submissions. Tag your project Built with BuildinginGRC.


Final learning check

Before you call the project complete, you should be able to explain these five things in your own words:

  1. Why the MCP is read-only against the audited system.

  2. Why the server stores evidence and returns a collection_id instead of returning everything directly.

  3. Why the GitHub token should have only the permissions the collector needs.

  4. Why a 404 or login wall is not automatically proof that a control is missing.

  5. What an API result proves versus what a screenshot proves.

If you can explain those, you did more than copy a project — you understand the GRC engineering decisions behind it.

F
license - not found
Not graded
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Converts audit trails from AIops agents into framework-mapped, tamper-evident compliance evidence bundles for HIPAA, PCI-DSS, SOC 2, and GDPR.
    19
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A local-first, model-neutral MCP server for collecting and normalizing change-scoped release evidence. It provides deterministic Git change summaries, evidence collection, and review bundles for agent review.
    7
    18
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Read-only MCP service for normalized public evidence from Web, X, YouTube, Reddit, and RSS. Owner-authenticated via Cloudflare Access, it exposes health, read, and transcript actions to ChatGPT and Codex.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server that produces scored, evidence-cited audits of public GitHub repos via tools for fetching metadata, reading files, scanning git history, and checking hygiene.
    MIT

View all related MCP servers

Related MCP Connectors

  • Screens public GitHub repos and PRs to generate risk maps, findings, and merge-readiness signals.

  • Source-first URL clone, capture, rebuild, and fidelity verification tools.

  • Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/LSDubose/my-evidence-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server