Academy
13 min read

How to Build an MCP Server (Part 2): Connect Real Data and Harden Security

Weeks 3–4 of the NextFlows Academy MCP course: wire tools to files or free APIs, write a data plan, prevent path traversal and SSRF, add timeouts, and pass an on-site code review.

Published July 19, 2026

What Part 2 covers

This is Part 2 of the NextFlows Academy MCP server course. You should already have a mentor-ready design doc, Zod schemas for your P0 tools, and a multi-tool skeleton that appears in MCP Inspector from Part 1 (Weeks 1–2).

Part 2 covers Weeks 3–4: connecting tools to real files or free public APIs, writing a data plan, handling fetch/parse failures, then hardening with a threat model, allowlists, timeouts, secrets hygiene, and an on-site code review.

When you finish Part 2, continue to Part 3: test, docs, and ship. The full cohort lives on the academy apply page.

Week 3 goal: at least three tools return real data

Replace `{ stub: true }` handlers with real backends for at least three P0 tools. Prefer fixtures committed under `./data/` so Demo Day still works if Wi‑Fi fails. Free APIs are allowed when they need no paid keys — for example Open-Meteo for weather.

Keep pure loaders in `src/lib/` and keep `registerTool` handlers thin. That split makes Week 4 hardening and Week 5 unit smoke tests straightforward.

Week 3 step-by-step

Step 1 — Branch from approved Week 2 main: `git checkout -b week-3-data`.

Step 2 — Choose sources per P0 tool. Mapping used in the academy: Notes/FAQ → Markdown or JSON under `./data/` · Expenses → CSV fixture · To-Do → JSON file · Weather → Open-Meteo plus a cached fixture fallback · Quotes → local quote bank or a free quotes API.

Step 3 — Write `docs/data-plan.md` (mandatory). Table columns: tool, source, fixture path, auth (should be none), failure modes, example response. Open or update a GitHub Issue titled Week 3 data.

Step 4 — Add safe I/O helpers. Implement a shared `fetchJson` with an 8–10 second timeout via `AbortSignal`. For files, resolve paths and keep reads under `./data` (Week 4 will tighten allowlists further).

Step 5 — Validate payloads with Zod after read/fetch. Empty results are valid — return `{ items: [] }` with a short message instead of crashing.

Step 6 — Wire real data (mandatory). Implement ≥3 P0 tools. Cap list sizes (for example top 10 hits) so responses stay model-friendly. Leave P1 tools stubbed if needed.

Step 7 — Optional resources. Register 1–3 read-only MCP resources (FAQ, sample notes) using the resources concept docs. Skip if short on time — tools alone can pass Week 3.

Step 8 — Demo evidence (mandatory). In Inspector, show three real-data successes and one clean failure path. Comment screenshots or a ≤2 minute Loom on your Week 3 Issue, including a short note on the failure you handled.

Week 4 goal: fail safely under hostile input

Treat model-supplied tool arguments like untrusted HTTP input. Week 4 is about path traversal, SSRF, secret leakage, runaway response size, and clear errors — then proving it in an on-site code review.

Use the OWASP Input Validation Cheat Sheet as a checklist mindset, not as an essay to copy. Your mitigations must map to your actual tools.

Week 4 step-by-step

Step 1 — Branch: `git checkout -b week-4-harden`.

Step 2 — Map attacks to your tools. File tools → path traversal. Fetch tools → SSRF via arbitrary URLs. Responses → leaking `.env`. Large CSV → unbounded loops and huge model context.

Step 3 — Write `docs/threat-model.md` (mandatory, ≤1 page). Cover assets, trust boundaries, top five risks for YOUR tools, mitigations this week, and out of scope. Mentors should see it before Monday on-site review.

Step 4 — Harden validation. Tighten Zod with `.max()`, enums, and rejects for empty required strings. File tools: `path.resolve` then require the result starts with your data directory. Fetch tools: allowlist hosts (for example only `api.open-meteo.com`). Never fetch user-provided arbitrary URLs.

Step 5 — Timeouts and caps. Every network call needs a timeout. Cap rows and character length in tool results; truncate with an explicit note.

Step 6 — Secrets hygiene. Ensure `.gitignore` covers `.env*`. Add `.env.example` with placeholders only. Prefer zero-secret designs for this cohort. If a secret ever landed in git, rotate it and follow GitHub’s sensitive data removal guide.

Step 7 — Open the harden PR (mandatory). Title it `harden: validations + errors + SECURITY.md`. Include a short SECURITY.md describing what you hardened and how to report issues. Attach a before/after Inspector shot of one blocked attack.

Step 8 — On-site code review (mandatory). Live-demo three P0 tools and one rejected attack. Complete `docs/review-checklist.md` with reviewer initials and dated action items. Fix P0 findings the same week, then merge.

Security checklist students should pass

☐ No path escapes outside `./data`. ☐ No arbitrary outbound URLs. ☐ Timeouts on every fetch. ☐ Output size capped. ☐ No secrets in repo or tool responses. ☐ Errors are short and actionable — no stack traces to the model. ☐ SECURITY.md exists. ☐ Threat model matches the code.

If any box is unchecked, Week 5 documentation will freeze a fragile system. Harden first.

Common Week 3–4 mistakes

Calling live APIs with no fixture fallback, then failing Demo Day offline.

Returning entire files or unbounded search results into the model context.

Building “security theater” docs that do not match the code paths.

Printing environment variables into logs or tool output while debugging.

Merging the harden PR before on-site review comments are addressed.

Continue the course

Frequently asked questions

Can my MCP tools call paid APIs during the academy?

Avoid paid keys for this cohort. Use local fixtures or free public APIs such as Open-Meteo. Zero-secret designs are easier to review and safer to demo.

What should I put in docs/data-plan.md?

One row per P0 tool with source, fixture path, auth (none), failure modes, and a happy-path example response. The file must match the paths your code actually reads.

What is SSRF in an MCP tool?

Server-side request forgery happens when a tool fetches a URL the model controls, which can reach internal hosts or unexpected services. Mitigate with host allowlists and by never accepting arbitrary URLs from tool arguments.

Do I need MCP resources to pass Week 3?

No. Resources are recommended for richer demos, but three P0 tools returning real data plus demo evidence is enough to pass Week 3 in this course.

What belongs in the Week 4 threat model?

Assets you protect, trust boundaries (model → args → disk/network), your top five risks, and the mitigations you will implement this week — not a generic OWASP essay.

How to Build an MCP Server (Part 2): Connect Real Data and Harden Security | Blog | NextFlows