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.