All work
shipped2026

Dark Matter Co-Pilot

MCP server that gives Claude access to real studio data

Solo Engineer

PythonFastMCPSQLitePydantic v2
ClaudeDesktopMCP clientMCP protocolFastMCPServerPython +Pydantic v2MCP TOOLSlist_case_studiescreate_leadlist_leadsupdate_lead_statuslist_projectslist_clientsrecord_website_findinglist_website_findingsdraft_outreach_emailhello_studioqueriesMCP RESOURCESstudio://pricingstudio://positioningstudio://processSQLiteDatabaseclientsleadsprojectscase_studieswebsite_findingsMarkdownfilespricing.mdpositioning.mdprocess.mdshipped

01 / Opener

I run a small web studio out of Pakistan. Most days I'm writing outreach, scoping projects, or deciding which past work to reference for a new lead. I kept asking Claude for help with all of it, and Claude was useful, but it had no idea what my actual studio does. Every conversation started with me re-explaining who I am, what I've built, and what I charge.

Got annoying enough that I built a tool to fix it.

02 / What it does

Dark Matter Co-Pilot is an MCP server that gives Claude access to my real studio data. Now in Claude Desktop I can:

  • Ask about my past client work and get real answers
  • Add and update leads through natural language
  • Have Claude analyze a prospect's website and save what it noticed
  • Draft cold outreach emails grounded in my actual case studies and voice

It all happens inside Claude Desktop. No separate dashboard, no logging in, no manual data entry I wouldn't be doing anyway.

03 / Demo

Two screenshots from actual use.

Asking about past work

Asking about past work

Claude pulls the case studies from SQLite, summarizes them, and notices things across all three (in this case, that they all use Next.js and Tailwind).

Drafting cold outreach

Drafting cold outreach

Claude reads the lead, pulls up any notes I've saved on their website, scans the case studies for the most relevant one, reads my voice guide and outreach template, then writes the email. Every detail in the output comes from real data.

04 / A few decisions worth explaining

Why MCP, not a chatbot on a website

The obvious version of this is a web app with a chat box. I didn't do that on purpose. A chatbot would compete with Claude itself, and Claude has the better interface, the better model, and most importantly my actual attention. My data layer doesn't need its own UI. It just needs to be reachable from where the conversation is already happening.

Tools return data, Claude writes words

None of my tools generate text. They return structured data. When Claude drafts an outreach email, the tool hands back: the lead info, the relevant case studies, my voice doc, and my outreach structure. Claude does the actual writing from that context.

This matters because it keeps the tool layer simple and predictable. If the email comes out weird, I can look at exactly what context Claude got, and I know it wasn't the tool fabricating anything.

Pydantic doing three jobs at once

The same Pydantic model that I use to convert a SQLite row to a Python object also defines the schema Claude sees when calling the tool, and the JSON that comes back out. One source of truth instead of three slightly different definitions floating around. Avoids the schema-drift mess you get on bigger projects.

05 / What's next

Next thing I want to add is a proposal generator for warm leads. Same architecture as the outreach drafter, just more context and a more formal output. I'll build it when I actually have warm leads to test it on.

What I'm deliberately not building: a web dashboard. The whole point of MCP is that the client (Claude Desktop) is already a good interface. Building a separate UI would just duplicate work Claude already does well.

Links

Built with Python · FastMCP · SQLite · Pydantic v2

Hello there!

Welcome to Saad's portfolio.