2026-06-19 · Architecture

Our MCP server is 160 lines

We put our whole CRM behind MCP last month — every table, document, dashboard, the chat, the calendar, the agents' own memory. 73 tools. I'd blocked out a week for it. It took an afternoon, and the server came out to 160 lines.

I keep going back to that number, so I want to write it down before it stops looking strange to me.

Here's the part that does the work. Not pseudocode — the file:

const mcpTools = AGENT_TOOLS
  .map(openaiToMcpTool)
  .filter(t => t && !SKIP_TOOLS.has(t.name));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  const result = await executeTool(name, args || {}, 1, context);
  return { content: [{ type: 'text', text: stringify(result) }] };
});

List the tools, run the tool. The schema converter is nine lines — it copies a name, a description and a JSON schema from one envelope into another:

function openaiToMcpTool(toolDef) {
  const fn = toolDef.function;
  if (!fn?.name) return null;
  return {
    name: fn.name,
    description: fn.description || '',
    inputSchema: fn.parameters || { type: 'object', properties: {} },
  };
}

There's no MCP mode. No bridge, no translation layer. The tools were already defined as function schemas, because that's how our own agents have always called them. When a human adds a row in the UI it runs add_table_row. When an agent adds a row it runs add_table_row — the same executeTool, no second code path, no endpoint written specially for the bot. So when MCP came along there was nothing to build. We wrote a nine-line adapter and pointed it at the executor we'd been using for years.

A detail, for honesty in both directions. We skip about fifteen tools on purpose — the agents' private scaffolding (planning, orchestration) and the file tools, since a client like Claude Code has its own. And this isn't npx-and-go: the bridge boots the real backend and wants a Postgres behind it. It's a server to a running CRM, not a toy. The trade is that you get all 73 tools over real, typed, related state.

I don't think 160 lines is impressive by itself. It's small because the expensive decision was made years earlier, somewhere that has nothing to do with MCP. That's the part I find interesting — and it's easier to see in the repo than to explain in a post.

It's open source, MIT. The bridge and all 73 tool definitions are there.

github.com/holetron/godcrm

Learn more →