This example demonstrates how to use Model Context Protocol to build a coding assistant that understands your codebase, development patterns, and can access APIs and documentation.
The Developer Copilot uses MCP to structure all the context needed for effective code assistance, including:
Code Repository Context
Project structure, file contents, and dependencies
Documentation Access
API documentation, coding standards, and best practices
Development Tools
Tools for code generation, refactoring, and documentation lookup
// Developer Copilot MCP Context
import { MCPContext } from '@modl/mcp';
const developerCopilot = new MCPContext({
systemInstruction: "You are a helpful coding assistant that helps developers write, understand, and debug code.",
userGoal: "Help the developer implement and improve their code efficiently.",
projectContext: {
name: "TaskManager",
language: "TypeScript",
framework: "React",
dependencies: [
{ name: "react", version: "18.2.0" },
{ name: "next", version: "14.0.0" },
{ name: "tailwindcss", version: "3.3.0" }
],
structure: [
{ path: "src/components/", description: "React components" },
{ path: "src/pages/", description: "Next.js pages" },
{ path: "src/lib/", description: "Utility functions and hooks" }
],
codingStandards: {
style: "Use functional components with hooks",
naming: "camelCase for variables, PascalCase for components",
testing: "Jest and React Testing Library"
}
},
tools: [
{
name: "searchDocumentation",
description: "Search API documentation",
parameters: {
query: "string",
source: "string"
}
},
{
name: "generateCode",
description: "Generate code based on a description",
parameters: {
description: "string",
language: "string",
context: "string"
}
},
{
name: "explainCode",
description: "Explain what a piece of code does",
parameters: {
code: "string",
detailLevel: "string"
}
},
{
name: "refactorCode",
description: "Suggest refactoring for a piece of code",
parameters: {
code: "string",
goal: "string"
}
}
],
memory: {}
});
export default developerCopilot;Structured representation of the codebase, dependencies, and coding standards.
projectContext: {
name: "TaskManager",
language: "TypeScript",
framework: "React",
dependencies: [
{ name: "react", version: "18.2.0" },
// More dependencies...
],
// More project details...
}Tools for code generation, explanation, and refactoring.
tools: [
{
name: "generateCode",
description: "Generate code based on a description",
parameters: {
description: "string",
language: "string",
context: "string"
}
},
// More tools...
]Once the MCP context is defined, it can be used with any LLM provider to create a personalized coding assistant:
import OpenAI from 'openai';
import developerCopilot from './developer-copilot.js';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function getCodeAssistance(userQuery, codeSnippet = null) {
// Update the context with the current code snippet if provided
if (codeSnippet) {
developerCopilot.updateContext({
currentCode: codeSnippet
});
}
// Compile the context for OpenAI
const context = developerCopilot.compileFor('openai');
// Prepare the messages
const messages = [
{
role: 'system',
content: context.systemMessage
},
{
role: 'user',
content: codeSnippet
? `${userQuery}
Here's the code I'm working with:
```
${codeSnippet}
````
: userQuery
}
];
// Use the context in your OpenAI call
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: messages,
tools: context.tools
});
return response.choices[0].message.content;
}
// Example usage
getCodeAssistance(
"Can you help me implement a React hook for fetching data with loading and error states?",
null
);Try out the Developer Copilot with this interactive demo. Ask for code examples, explanations, or refactoring suggestions.
Hello! I'm your Developer Copilot for the TaskManager project. How can I help you with your code today?
Can you help me implement a React hook for fetching data with loading and error states?
I'd be happy to help you implement a React hook for data fetching with loading and error states. Here's a custom hook that follows the project's coding standards:
// src/lib/hooks/useFetch.ts
import { useState, useEffect } from 'react';
interface UseFetchOptions {
initialData?: any;
dependencies?: any[];
}
export function useFetch<T>(
url: string,
options?: UseFetchOptions
) {
const [data, setData] = useState<T | undefined>(
options?.initialData
);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
let isMounted = true;
const fetchData = async () => {
setIsLoading(true);
setError(null);
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`Error ${response.status}: ${response.statusText}`
);
}
const result = await response.json();
if (isMounted) {
setData(result);
}
} catch (err) {
if (isMounted) {
setError(err instanceof Error ? err : new Error(String(err)));
}
} finally {
if (isMounted) {
setIsLoading(false);
}
}
};
fetchData();
return () => {
isMounted = false;
};
}, [url, ...(options?.dependencies || [])]);
return { data, isLoading, error };
}You can use this hook in your components like this:
// src/components/TaskList.tsx
import { useFetch } from '../lib/hooks/useFetch';
interface Task {
id: string;
title: string;
completed: boolean;
}
export function TaskList() {
const {
data: tasks,
isLoading,
error
} = useFetch<Task[]>('/api/tasks');
if (isLoading) return <div>Loading tasks...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{tasks?.map(task => (
<li key={task.id}>{task.title}</li>
))}
</ul>
);
}This hook follows the project's TypeScript and React standards. Would you like me to explain any part of this implementation in more detail?
This is a demo interface. The copilot is not actually functional.