The Power of Local MCP Servers
August 20, 2025LLMs are transforming the way we do software development, coding agents offer a significant productivity gain in an increasing number of tasks. However, they often fail on project-specific execution, like running contextually appropriate commands. Model Context Protocol (MCP) helps to address this by acting as an interface between agents and your codebase. Local MCP servers become the project-specific guide that provides precise, controlled context when agents need it.
Why use MCP
Consider test execution: Agents might correctly guess the right commands in extremely simple projects, but fail as complexity and nuance increases, by having multiple applications in one repository, mixed languages or conventions.
Instead of documenting everything the agent might need to know in a prompt or instructions file, we’ll put that information behind an MCP server exposed as tools, this enables the agent to retrieve a targeted, small piece of curated context when it needs it, resulting in a higher signal-to-noise-ratio, making relevant information stand out.
Setting up a local MCP server for your project is surprisingly straightforward.
Local MCP Setup
Here’s how to set up a local MCP server for our example project. We’ll create a very simple server with a single tool that the agent will call when it needs to run tests.
Let’s set a scenario in which we have two applications living in a single repository, a python server and a react frontend, the dev-mcp
folder is where we’ll store our mcp server, we’ll use python for the MCP server in the example but any language will do, MCP provides SDKs for different languages. You’ll have to add the relevant dependencies in your project using the package manager of your choice and adapt it to your specific needs.
project/
├── dev-mcp/
│ └── server.py
├── frontend/
└── server/
# server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("dev-mcp")
@mcp.tool()
def get_test_commands(application: str) -> str:
"""Get test running commands for an application.
Returns detailed instructions to run tests
Args:
application: The application component to get test commands for.
Valid options: "server", "frontend"
"""
valid_applications = ["server", "frontend"]
if application not in valid_applications:
raise ValueError(
f"Invalid application '{application}'. Valid options are: {', '.join(valid_applications)}"
)
commands = {
"server": """```bash
cd server/
# Prefer to run tests without coverage unless coverage is specifically needed,
# in which case remove --no-cov from the command
# Run a specific test
uv run pytest [path-to-file] --no-cov
# Example: uv run pytest tests/api/test_users.py --no-cov
# Run a specific test case using a single worker, fastest single test case
uv run pytest [path-to-file] --no-cov -k [test-case-name] -n 0
# Example: uv run pytest tests/services/test_auth.py --no-cov -k test_login -n 0
# Run integration tests
uv run pytest -m "integration" --no-cov
# Run all tests
uv run pytest --no-cov
```""",
"frontend": """```bash
cd frontend/
# Run a specific test file, faster
npm run test [path-to-file]
# Example: npm run test src/components/Button.test.ts
# Run all tests matching a specific pattern
npm run test [pattern]
# Example: npm run test auth
# Run all tests
npm run test
# Run all tests with coverage
npm run test:coverage
```""",
}
return commands[application]
if __name__ == "__main__":
mcp.run()
The agent will call get_test_commands
with an argument of server
or frontend
and it will be returned those small snippets containing detailed instructions, the agent is then smart enough to pick the right one for the use case.
VSCode integration
Now that we have the server, the next step is integrating it into our workflow. Integrating the MCP server into your workflow is straightforward. Using VSCode as an example, the setup is simple and provides a seamless experience to your team.
We’ll add a .vscode/mcp.json
file in our project with the configuration pointing to our server.
project/
├── .vscode/
│ └── mcp.json
├── dev-mcp/
│ └── server.py
├── frontend/
└── server/
{
"servers": {
"dev-mcp": {
"command": "uv",
"args": ["run", "--directory", "dev-mcp", "python", "server.py"],
"dev": {
"watch": "dev-mcp/**/*.py"
}
}
}
}
With this configuration, we tell VSCode which command to run our server with and it’s arguments. The dev
key and watch property configures VSCode to automatically restart our server whenever files matching the pattern change. This allows everyone working on the project to quickly use, contribute and iterate on the MCP server.
If your agent is not picking up and using the tools already, make sure that the agent has the tools enabled.
Usage Example
To guide the agent’s behavior, we must explicitly instruct the agent to use our MCP server. While you can add this to individual prompts, it’s most practical to include it in a persistent instructions file, like copilot-instructions.md
.
.github/copilot-instructions.md
## Development MCP Server
The `dev-mcp` server is **your primary tool** - it has authoritative information about this codebase.
Default to use the MCP server whenever it applies.
**ALWAYS use MCP tools FIRST** before:
- Running tests
Then use a prompt that will require the agent to use a tool in order to do it properly.
Your prompt
I'm tasked with increasing the coverage of the frontend codebase, can you tell me which components need coverage the most?
Agent response (abridged)
I'll help you identify which frontend components need test coverage the most. Let me start by using the MCP server to get the correct test commands for the frontend application, then analyze the current test coverage.
> tool call get_test_commands
Now let me run the command to run the test with coverage to see the current state
> run command in terminal `cd frontend && npm run test:coverage`
Perfect! I can see the test coverage report...
Practical tips
Get the setup done early. Getting the setup done early lowers the barrier to experimentation and iteration. The effort required to add new tools becomes negligible, encouraging quick prototyping of ideas.
Iterate on the agent instructions. We’ve seen how to position the MCP server so that it is used effectively. Regularly refine these instructions based on agent performance and the development of the MCP server.
Curate agent-specific documentation. Think of each tool as a focused extension of your prompt. Be concise and provide only the information you want the agent to act on, not what a human might need.
View agent failure as an opportunity. When an agent fails, treat it as a signal to improve your tools. A failed task often indicates a gap in context that a new tool can fill.
Think beyond documentation. While this article focused on providing documentation, MCP tools can also be actions. Explore the possibilities of augmenting recurring tasks or complex operations with custom tools.
Conclusion
Coding agents are here to stay, but their value is proportional to the quality of our inputs—our prompts, tools, and codebase. The Model Context Protocol (MCP) plays a crucial role in this equation.
By implementing local, project-specific MCP servers, you can bridge the critical gap between a general-purpose model and your unique codebase. It provides a portable, shared mechanism to supply agents with the precise, curated context they need to solve specific problems. The possibilities extend far beyond this example. You can empower agents to run multi-step workflows like generating and running migrations, measure query performances, or follow troubleshooting guides for common issues.
The effort you put into these tools will not only level up your codebase but also your team, enabling a more effective and efficient AI-boosted development workflow.