
Cursor + MCP + Fine-Tuned Model: Domain AI Inside Your Code Editor
Cursor supports MCP servers. Connect your fine-tuned domain model to Cursor and get specialized AI capabilities inside the editor — code generation trained on your codebase, documentation in your style, domain-specific autocomplete.
Cursor is the AI-native code editor most vibecoders use daily. It supports MCP servers — which means you can connect your fine-tuned model to Cursor and invoke domain-specific AI capabilities directly from your coding environment, without switching context.
The use cases: a code documentation model trained on your codebase's style, a domain-specific code generator trained on your patterns, a content model that writes in your product's voice, all accessible as Cursor tools.
Why Domain Models Beat General Models in Cursor
Cursor's built-in AI (Claude Sonnet, GPT-4o) is excellent for general coding tasks. It struggles on:
Your codebase's specific patterns: Generic AI does not know your team's naming conventions, architecture decisions, or the libraries you have chosen to standardize on. It will generate syntactically correct code that does not fit your codebase.
Your documentation style: Generic AI writes generic documentation. A model trained on your existing docs writes documentation that sounds like the rest of your docs.
Domain-specific logic: If your app handles complex business logic (tax calculations, healthcare workflows, legal document processing), generic AI makes educated guesses. A model trained on your domain logic generates correct business logic.
A fine-tuned model trained on your codebase and domain produces outputs that a senior developer on your team would recognize as fitting.
Setting Up the MCP Server for Cursor
Cursor reads MCP configuration from ~/.cursor/mcp.json (or project-level .cursor/mcp.json).
Step 1: Build a code-focused MCP server
// cursor-domain-mcp/server.mjs
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
const OLLAMA_URL = 'http://localhost:11434/api/chat';
const MODEL = 'my-codebase-model';
const server = new Server(
{ name: 'codebase-assistant', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'generate_code',
description: 'Generate code following the project\'s specific patterns, naming conventions, and library choices. Use for creating new functions, components, or modules that should match existing code style.',
inputSchema: {
type: 'object',
properties: {
description: { type: 'string', description: 'What code to generate' },
file_context: { type: 'string', description: 'Relevant existing code from the codebase for context' },
language: { type: 'string', description: 'Programming language or framework' }
},
required: ['description']
}
},
{
name: 'write_documentation',
description: 'Write documentation in the project\'s established style — same format, same level of detail, same terminology. Use for JSDoc, README sections, or inline comments.',
inputSchema: {
type: 'object',
properties: {
code: { type: 'string', description: 'The code to document' },
doc_type: { type: 'string', description: 'jsdoc, readme, comment, or api-reference' }
},
required: ['code']
}
},
{
name: 'domain_query',
description: 'Answer domain-specific questions about the business logic, industry rules, or specialized requirements that the codebase implements.',
inputSchema: {
type: 'object',
properties: {
question: { type: 'string', description: 'The domain question to answer' }
},
required: ['question']
}
}
]
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
let prompt;
if (name === 'generate_code') {
prompt = `Generate code for: ${args.description}
${args.file_context ? `\nExisting code context:\n${args.file_context}` : ''}
${args.language ? `\nLanguage/Framework: ${args.language}` : ''}`;
} else if (name === 'write_documentation') {
prompt = `Write ${args.doc_type || 'documentation'} for this code:\n\n${args.code}`;
} else if (name === 'domain_query') {
prompt = args.question;
} else {
throw new Error(`Unknown tool: ${name}`);
}
const response = await fetch(OLLAMA_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: MODEL,
messages: [{ role: 'user', content: prompt }],
stream: false
})
});
const data = await response.json();
return { content: [{ type: 'text', text: data.message.content }] };
});
const transport = new StdioServerTransport();
await server.connect(transport);
Step 2: Add to Cursor MCP config
Create or edit ~/.cursor/mcp.json:
{
"mcpServers": {
"codebase-assistant": {
"command": "node",
"args": ["/absolute/path/to/cursor-domain-mcp/server.mjs"]
}
}
}
Restart Cursor. The tools appear in the Cursor chat panel.
Training the Right Model for Cursor Integration
For code generation: Training data should be (task description, correct implementation) pairs from your own codebase. Extract from your git history: commit messages + the diff = (task, implementation) pairs.
For documentation: Training data: existing documented functions — (code block, corresponding docstring/README section) pairs.
For domain knowledge: Training data: internal wikis, architecture decision records, domain glossaries, existing Q&A from Slack or Confluence. Convert to (question, answer) format.
Using the Model in Cursor Chat
In Cursor's chat panel (Cmd+L / Ctrl+L), you can invoke your tools:
"Use codebase-assistant to generate a new API endpoint for [description]"
Or let Cursor invoke it automatically when it recognizes the pattern matches your tool's description. The more specific your tool description, the more accurately Cursor routes to it vs its built-in model.
Practical workflow for a solo developer:
- Open Cursor Chat
- Paste the signature / interface you want implemented
- Cursor invokes
generate_codetool → your fine-tuned model generates implementation in your style - Cursor shows the generated code + explains it
- Apply to file
The model does not replace Cursor's built-in intelligence — it augments it with knowledge of your specific codebase.
Ship AI that runs on your users' devices.
Ertas early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.
Further Reading
- MCP + Fine-Tuned Local Model — The architecture overview
- Claude Desktop Local Model Setup — Same pattern in Claude Desktop
- Windsurf + Fine-Tuned Model Setup — Windsurf IDE + local model
- MCP Tools for Agency Client Workflows — Agency use cases
Ship AI that runs on your users' devices.
Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.
Keep reading

MCP + Fine-Tuned Local Model: Connect Claude to Your Domain-Specific AI
Model Context Protocol (MCP) lets Claude Desktop talk to any server — including your own Ollama-hosted fine-tuned model. Here's the architecture and setup for routing Claude requests to a custom domain model.

MCP Servers + Local Models: Zero API Costs for Domain-Specific AI Tools
The combination of MCP servers and fine-tuned local models eliminates per-token costs for AI tools built on Claude, Cursor, and other MCP-compatible clients. Here's the cost math and the architecture.

Replit App AI Costs Exploding? Replace OpenAI with a Fine-Tuned Local Model
Replit's always-on deployment and easy AI integration create a specific API cost problem. Here's how to replace OpenAI with a fine-tuned local model and cut costs to flat rate.