Role-Specific Context MCP Server

by Chris-June
Verified
# Role-Context MCP: Step-by-Step Tutorial ## Introduction This tutorial will guide you through using the Role-Context MCP server with practical examples. We'll cover basic setup, creating custom roles, processing queries, and more advanced features. ## Prerequisites - Node.js 18+ installed - Basic knowledge of JavaScript/TypeScript - OpenAI API key ## Setup 1. Clone the repository and install dependencies: ```bash git clone https://github.com/yourusername/role-context-mcp.git cd role-context-mcp npm install ``` 2. Create a `.env` file with your OpenAI API key: ``` OPENAI_API_KEY=your_api_key_here OPENAI_MODEL=gpt-4o-mini ``` 3. Build and start the server: ```bash npm run build npm run start:http ``` ## Tutorial 1: Basic Query Processing ### Step 1: Create a test script Create a file called `test-query.js`: ```javascript const axios = require('axios'); async function testQuery() { try { const response = await axios.post('http://localhost:3000/process', { roleId: 'marketing-expert', query: 'How can I improve my social media engagement?' }); console.log('Response:', response.data.response); } catch (error) { console.error('Error:', error.response?.data || error.message); } } testQuery(); ``` ### Step 2: Run the script ```bash node test-query.js ``` You should see a response from the marketing expert role with advice on improving social media engagement. ## Tutorial 2: Creating a Custom Role ### Step 1: Create a test script Create a file called `create-role.js`: ```javascript const axios = require('axios'); async function createCustomRole() { try { const response = await axios.post('http://localhost:3000/roles', { id: 'tech-writer', name: 'Technical Writer', description: 'Specializes in clear, concise technical documentation', instructions: 'Create documentation that is accessible to both technical and non-technical audiences', domains: ['technical-writing', 'documentation', 'tutorials'], tone: 'technical', systemPrompt: 'You are an experienced technical writer with expertise in creating clear, concise documentation for complex systems.' }); console.log('Custom role created:', response.data.role); } catch (error) { console.error('Error:', error.response?.data || error.message); } } createCustomRole(); ``` ### Step 2: Run the script ```bash node create-role.js ``` ### Step 3: Test the new role Create a file called `test-custom-role.js`: ```javascript const axios = require('axios'); async function testCustomRole() { try { const response = await axios.post('http://localhost:3000/process', { roleId: 'tech-writer', query: 'Write a short introduction paragraph for a REST API documentation' }); console.log('Response:', response.data.response); } catch (error) { console.error('Error:', error.response?.data || error.message); } } testCustomRole(); ``` ### Step 4: Run the script ```bash node test-custom-role.js ``` You should see a response from your custom technical writer role with an introduction paragraph for REST API documentation. ## Tutorial 3: Changing a Role's Tone ### Step 1: Create a test script Create a file called `change-tone.js`: ```javascript const axios = require('axios'); async function changeTone() { try { // First, get available tones const tonesResponse = await axios.get('http://localhost:3000/tones'); console.log('Available tones:', Object.keys(tonesResponse.data.tones)); // Change the tone of the tech-writer role to 'casual' const response = await axios.patch('http://localhost:3000/roles/tech-writer', { tone: 'casual' }); console.log('Role updated:', response.data.role); } catch (error) { console.error('Error:', error.response?.data || error.message); } } changeTone(); ``` ### Step 2: Run the script ```bash node change-tone.js ``` ### Step 3: Test the role with the new tone Run the previous script again to see how the response changes with the new tone: ```bash node test-custom-role.js ``` You should notice that the response now has a more casual tone compared to the previous technical tone. ## Tutorial 4: Storing and Using Memories ### Step 1: Create a test script Create a file called `store-memory.js`: ```javascript const axios = require('axios'); async function storeMemory() { try { const response = await axios.post('http://localhost:3000/memories', { roleId: 'marketing-expert', content: 'The user prefers Instagram over TikTok for their business', type: 'user', importance: 'medium' }); console.log('Memory stored:', response.data.memory); } catch (error) { console.error('Error:', error.response?.data || error.message); } } storeMemory(); ``` ### Step 2: Run the script ```bash node store-memory.js ``` ### Step 3: Test how the memory affects responses Create a file called `test-memory.js`: ```javascript const axios = require('axios'); async function testMemory() { try { const response = await axios.post('http://localhost:3000/process', { roleId: 'marketing-expert', query: 'What social media platform should I focus on for my business?' }); console.log('Response:', response.data.response); } catch (error) { console.error('Error:', error.response?.data || error.message); } } testMemory(); ``` ### Step 4: Run the script ```bash node test-memory.js ``` You should notice that the response now takes into account the stored memory about the user's preference for Instagram. ## Tutorial 5: Building a Simple Chat Interface ### Step 1: Create an HTML file Create a file called `simple-chat.html`: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Role-Based Chat</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } .chat-container { display: flex; flex-direction: column; gap: 20px; } .role-selector { margin-bottom: 20px; } select, textarea, button { padding: 10px; font-size: 16px; } textarea { width: 100%; height: 100px; } button { background-color: #4CAF50; color: white; border: none; cursor: pointer; } button:disabled { background-color: #cccccc; } .response { border: 1px solid #ddd; padding: 15px; border-radius: 5px; background-color: #f9f9f9; } .loading { display: inline-block; width: 20px; height: 20px; border: 3px solid rgba(0,0,0,.3); border-radius: 50%; border-top-color: #000; animation: spin 1s ease-in-out infinite; } @keyframes spin { to { transform: rotate(360deg); } } </style> </head> <body> <h1>Role-Based Chat</h1> <div class="chat-container"> <div class="role-selector"> <label for="role-select">Select Role:</label> <select id="role-select"></select> </div> <div> <textarea id="query" placeholder="Type your question here..."></textarea> </div> <div> <button id="submit-btn">Submit</button> </div> <div id="response-container" class="response" style="display: none;"> <h2>Response:</h2> <div id="response-content"></div> </div> </div> <script> // DOM elements const roleSelect = document.getElementById('role-select'); const queryInput = document.getElementById('query'); const submitBtn = document.getElementById('submit-btn'); const responseContainer = document.getElementById('response-container'); const responseContent = document.getElementById('response-content'); // API URL const API_URL = 'http://localhost:3000'; // Fetch roles when page loads async function fetchRoles() { try { const response = await fetch(`${API_URL}/roles`); const data = await response.json(); // Populate role select data.roles.forEach(role => { const option = document.createElement('option'); option.value = role.id; option.textContent = role.name; roleSelect.appendChild(option); }); } catch (error) { console.error('Error fetching roles:', error); alert('Error fetching roles. Is the server running?'); } } // Process query async function processQuery() { const roleId = roleSelect.value; const query = queryInput.value.trim(); if (!roleId || !query) { return; } // Show loading state submitBtn.disabled = true; submitBtn.innerHTML = '<span class="loading"></span> Processing...'; try { const response = await fetch(`${API_URL}/process`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ roleId, query }), }); const data = await response.json(); // Display response responseContent.innerHTML = data.response.replace(/\n/g, '<br>'); responseContainer.style.display = 'block'; } catch (error) { console.error('Error processing query:', error); alert('Error processing query: ' + error.message); } finally { // Reset loading state submitBtn.disabled = false; submitBtn.textContent = 'Submit'; } } // Event listeners submitBtn.addEventListener('click', processQuery); // Initialize fetchRoles(); </script> </body> </html> ``` ### Step 2: Open the HTML file in a browser You can open this file directly in your browser, or serve it using a simple HTTP server: ```bash npx http-server -p 8080 ``` Then navigate to `http://localhost:8080/simple-chat.html` in your browser. ## Tutorial 6: Using the MCP Client ### Step 1: Create a test script Create a file called `mcp-client.js`: ```javascript const { createClient } = require('@modelcontextprotocol/sdk/client'); async function testMcpClient() { try { // Create MCP client const client = await createClient({ transport: 'stdio', serverCommand: 'npm run start:mcp', serverCwd: process.cwd(), }); console.log('MCP client connected'); // Get available resources const resources = await client.getResources(); console.log('Available resources:', resources); // Process a query with a specific role const response = await client.executeToolRequest({ name: 'process-with-role', parameters: { roleId: 'marketing-expert', query: 'How can I improve my email marketing campaigns?' } }); console.log('Response:', response); // Close the client await client.close(); } catch (error) { console.error('Error:', error); } } testMcpClient(); ``` ### Step 2: Run the script ```bash node mcp-client.js ``` ## Conclusion Congratulations! You've completed the tutorial and learned how to: 1. Process queries with predefined roles 2. Create custom roles 3. Change a role's tone 4. Store and use memories 5. Build a simple chat interface 6. Use the MCP client For more advanced features and detailed API documentation, refer to the [API_DOCUMENTATION.md](./API_DOCUMENTATION.md) and [ARCHITECTURE.md](./ARCHITECTURE.md) files.