Build a local MCP server and inventory every tool it exposes
Task
Set up a small Model Context Protocol server inside your lab, describe it in a client configuration you write yourself, and produce an inventory of what it lets a model see and do. One of its tools is deliberately too broad. Find it from the inventory, narrow it, and prove the narrowing with the canary string rather than by reading your own code and trusting it.
Steps
- Create
~/secai-lab/mcp/lab_server.pyusing the SDK's FastMCP helper. Expose four tools:search_docs(query), a keyword search overdocs/that returns file names and first lines;read_doc(name);append_note(text), which appends tolab/notes.md; andread_file(path), which reads whatever path it is given. The last one is deliberately too broad, and it is the finding this lab exists to catch. Add one resource that serves the product FAQ. - Write the client configuration
~/secai-lab/mcp/client-config.jsonin themcpServersshape most MCP clients read: a server name, thecommandandargsthat launch it, and anenvblock. The lab server needs no credentials, so nothing secret belongs in this file. That absence is one of the things you will check. - Write
~/secai-lab/mcp/list_tools.py, which launches the server over stdio with the SDK's client, initialises a session and callslist_tools()andlist_resources(). Write the tools tolab/mcp-tools.jsonas a list of objects withname,descriptionandinput_schema, and the resources tolab/mcp-resources.json. This is what a connected model is told it can do. Read the descriptions as model input, because that is what they are. - Write
lab/mcp-tool-inventory.csvwith headerserver,kind,name,reads,writes,data_reach,needs_approval,verdict, one row per tool and per resource.kindis tool, resource or prompt;data_reachnames the widest thing the entry can touch;writesandneeds_approvalare yes or no;verdictis keep, narrow or remove. Any entry that writes needs approval. - Write
~/secai-lab/mcp/probe.py, which callsread_filewithdocs/restricted/salaries.mdthrough the SDK client and prints the result. Run it now and count the canary in its output. It will be there. Write the count inlab/mcp-review.md, because a check you have never seen fail has not shown that it detects anything. - Narrow the server.
read_filemust resolve the path it is given, so that..cannot climb out, and refuse anything outsidedocs/or underdocs/restricted/.append_notemust refuse text above a fixed length. Update the inventory's verdicts, then rerunlist_tools.pyand the probe. - Add one line to
lab/mcp-review.mdfor each of the lesson's six vetting questions as they apply to this server: data flow, permissions, identity and credentials, agency, provenance and observability. Start each line with-.
Verify
cd ~/secai-lab
python mcp/list_tools.py
python - <<'EOF'
import csv, json
exposed = {t['name'] for t in json.load(open('lab/mcp-tools.json'))}
inv = {r['name']: r for r in csv.DictReader(open('lab/mcp-tool-inventory.csv'))}
print('exposed tools:', sorted(exposed))
print('exposed but not inventoried:', sorted(exposed - set(inv)) or 'none')
loose = [n for n, r in inv.items() if r['writes'] == 'yes' and r['needs_approval'] != 'yes']
print('write-capable entries with no approval:', loose or 'none')
EOF
python mcp/probe.py | grep -c CANARY-7Q4X-SECAI
grep -ciE 'key|token|secret|password' mcp/client-config.json
grep -c '^- ' lab/mcp-review.md
Four exposed tools, none missing from the inventory, and no write-capable entry without approval. The probe's canary count must now be 0, where your first run in step 5 found at least one. The credential search of the client configuration must print 0, and the review must have six lines. If the probe still finds the canary, the path check runs before the path is resolved, which is the usual mistake.
Notes
The descriptions in lab/mcp-tools.json are worth a second look. A model decides which tool to call partly from that text, which is why a malicious server can steer a model through its own tool descriptions. Your server's descriptions are honest because you wrote them. A community server's are whatever its author wrote, and that is the supply-chain point the lesson makes.
This is an independent study companion for CompTIA SecAI+ CY0-001 and is not produced by or endorsed by CompTIA.