/* * Chat MCP Server Example * * This example demonstrates how to create an MCP server that provides * chat-related prompts for different conversation scenarios. It shows how to * implement and register multiple prompt templates. * * Compile with: * valac --pkg mcp-vala --pkg json-glib-1.0 --pkg gee-0.8 --pkg posix chat-server.vala -o chat-server */ using Mcp; using Posix; /** * Chat server that provides conversation prompts. */ public class ChatServer : GLib.Object { private Mcp.Core.Server server; /** * Creates a new ChatServer. */ public ChatServer () { // Create server information var server_info = new Mcp.Types.Protocol.ServerInfo ( "chat-server", "1.0.0" ); server_info.description = "MCP server providing chat and conversation prompts"; // Create server capabilities with prompts enabled var capabilities = new Mcp.Types.Protocol.ServerCapabilities (); capabilities.logging = true; capabilities.prompts = new Mcp.Types.Protocol.PromptsCapabilities (); // Create server server = new Mcp.Core.Server (server_info, capabilities); // Register chat prompt templates setup_prompts (); } /** * Sets up chat prompt templates. */ private void setup_prompts () { // Register conversation starter prompt var conversation_starter = new ConversationStarterPrompt (); try { server.prompt_manager.register_template ("conversation_starter", conversation_starter); } catch (Error e) { GLib.stderr.printf ("Failed to register conversation starter prompt: %s\n", e.message); } // Register code review prompt var code_review = new CodeReviewPrompt (); try { server.prompt_manager.register_template ("code_review", code_review); } catch (Error e) { GLib.stderr.printf ("Failed to register code review prompt: %s\n", e.message); } // Register brainstorming prompt var brainstorming = new BrainstormingPrompt (); try { server.prompt_manager.register_template ("brainstorming", brainstorming); } catch (Error e) { GLib.stderr.printf ("Failed to register brainstorming prompt: %s\n", e.message); } // Register interview prompt var interview = new InterviewPrompt (); try { server.prompt_manager.register_template ("interview", interview); } catch (Error e) { GLib.stderr.printf ("Failed to register interview prompt: %s\n", e.message); } // Register story writing prompt var story_writing = new StoryWritingPrompt (); try { server.prompt_manager.register_template ("story_writing", story_writing); } catch (Error e) { GLib.stderr.printf ("Failed to register story writing prompt: %s\n", e.message); } } /** * Runs the server. * * @return Exit code */ public async int run () { try { // Start the server bool started = yield server.start (); if (!started) { GLib.stderr.printf ("Failed to start server\n"); return 1; } // Chat server started successfully // Available prompts: conversation_starter, code_review, brainstorming, interview, story_writing // Waiting for MCP client connections... // Run the main loop var main_loop = new MainLoop (); // Connect shutdown signal server.shutdown.connect (() => { main_loop.quit (); }); main_loop.run (); return 0; } catch (Error e) { GLib.stderr.printf ("Server error: %s\n", e.message); return 1; } } } /** * Conversation starter prompt template. */ public class ConversationStarterPrompt : Mcp.Prompts.BaseTemplate { /** * Creates a new ConversationStarterPrompt. */ public ConversationStarterPrompt () { base ("conversation_starter", "Conversation Starter", "Generates conversation starter prompts for different contexts"); // Add arguments add_argument ("context", "Context", "The context or situation for the conversation (e.g., professional, casual, networking)", true); add_argument ("topic", "Topic", "The main topic to discuss", false); add_argument ("tone", "Tone", "The tone of the conversation (formal, casual, friendly, enthusiastic)", false); add_argument ("participants", "Participants", "Number of participants expected", false); } /** * {@inheritDoc} */ protected override Gee.ArrayList generate_messages (GLib.Variant arguments) { var messages = new Gee.ArrayList (); string context = get_string_arg_variant (arguments, "context"); string? topic = get_string_arg_variant (arguments, "topic", null); string? tone = get_string_arg_variant (arguments, "tone", null); int? participants = get_int_arg_variant (arguments, "participants", 2); string template = """Generate a conversation starter for a {{context}} context{{#topic}} focused on {{topic}}{{/topic}}{{#tone}} with a {{tone}} tone{{/tone}}{{#participants}} for {{participants}} participants{{/participants}}. The conversation starter should: 1. Be appropriate for the specified context 2. Engage participants naturally 3. Set a positive and collaborative atmosphere 4. Lead to meaningful discussion 5. Be concise but inviting Please provide 3-5 different conversation starter options, each with a brief explanation of when it would be most effective."""; messages.add (create_user_message (template, arguments)); return messages; } /** * Gets a string argument from the arguments object. */ private string? get_string_arg_variant (GLib.Variant arguments, string name, string? default_value = null) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("s")).get_string (); } return default_value; } /** * Gets an integer argument from the arguments object. */ private int get_int_arg_variant (GLib.Variant arguments, string name, int default_value = 0) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("i")).get_int32 (); } return default_value; } } /** * Code review prompt template. */ public class CodeReviewPrompt : Mcp.Prompts.BaseTemplate { /** * Creates a new CodeReviewPrompt. */ public CodeReviewPrompt () { base ("code_review", "Code Review", "Generates a comprehensive code review prompt"); // Add arguments add_argument ("code", "Code", "The code to review", true); add_argument ("language", "Language", "Programming language of the code", true); add_argument ("focus", "Focus Area", "Specific areas to focus on (security, performance, readability, best_practices, all)", false); add_argument ("experience_level", "Experience Level", "Target experience level (beginner, intermediate, advanced)", false); add_argument ("file_type", "File Type", "Type of file (function, class, module, script, config)", false); } /** * {@inheritDoc} */ protected override Gee.ArrayList generate_messages (GLib.Variant arguments) { var messages = new Gee.ArrayList (); string code = get_string_arg_variant (arguments, "code"); string language = get_string_arg_variant (arguments, "language"); string? focus = get_string_arg_variant (arguments, "focus", "all"); string? experience_level = get_string_arg_variant (arguments, "experience_level", "intermediate"); string? file_type = get_string_arg_variant (arguments, "file_type", "code"); string template = """Please perform a comprehensive code review of the following {{language}} {{file_type}}: ```{{language}} {{code}} ``` Review Focus: {{focus}} Target Audience: {{experience_level}} developers Please analyze the code and provide feedback on: 1. **Code Quality & Readability** - Clarity and maintainability - Naming conventions - Code organization and structure - Comments and documentation 2. **Functionality & Logic** - Correctness of implementation - Edge cases handled - Algorithm efficiency - Logic flow and control structures 3. **Best Practices & Standards** - Language-specific conventions - Design patterns usage - Error handling - Security considerations 4. **Performance & Optimization** - Time and space complexity - Resource usage - Potential bottlenecks - Optimization opportunities 5. **Testing & Maintainability** - Testability of the code - Modularity and reusability - Coupling and cohesion - Future extensibility {{#focus}} For the {{focus}} focus, please pay special attention to: - Security vulnerabilities and potential exploits - Performance bottlenecks and optimization opportunities - Code readability and maintainability issues - Adherence to established best practices {{/focus}} Please provide: - Specific line-by-line feedback where relevant - Overall assessment and summary - Concrete suggestions for improvement - Positive aspects worth noting - Priority levels for issues found (critical, high, medium, low) Format your response constructively with clear explanations and actionable recommendations."""; messages.add (create_user_message (template, arguments)); return messages; } /** * Gets a string argument from the arguments object. */ private string? get_string_arg_variant (GLib.Variant arguments, string name, string? default_value = null) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("s")).get_string (); } return default_value; } } /** * Brainstorming prompt template. */ public class BrainstormingPrompt : Mcp.Prompts.BaseTemplate { /** * Creates a new BrainstormingPrompt. */ public BrainstormingPrompt () { base ("brainstorming", "Brainstorming", "Generates structured brainstorming prompts"); // Add arguments add_argument ("topic", "Topic", "The main topic or problem to brainstorm", true); add_argument ("brainstorm_type", "Type", "Type of brainstorming (ideas, solutions, pros_cons, mind_map)", false); add_argument ("constraints", "Constraints", "Any constraints or limitations to consider", false); add_argument ("time_limit", "Time Limit", "Time limit for brainstorming session in minutes", false); add_argument ("participants", "Participants", "Number of participants", false); } /** * {@inheritDoc} */ protected override Gee.ArrayList generate_messages (GLib.Variant arguments) { var messages = new Gee.ArrayList (); string topic = get_string_arg_variant (arguments, "topic"); string? brainstorm_type = get_string_arg_variant (arguments, "brainstorm_type", "ideas"); string? constraints = get_string_arg_variant (arguments, "constraints", null); int? time_limit = get_int_arg_variant (arguments, "time_limit", 30); int? participants = get_int_arg_variant (arguments, "participants", 1); string template = """Facilitate a {{brainstorm_type}} brainstorming session for the following topic: **Topic:** {{topic}} {{#constraints}} **Constraints/Limitations:** {{constraints}} {{/constraints}} **Session Details:** - Duration: {{time_limit}} minutes - Participants: {{participants}} - Type: {{brainstorm_type}} brainstorming Please structure the session as follows: 1. **Warm-up (2-3 minutes)** - Briefly restate the topic and objectives - Set positive, creative atmosphere - Establish basic ground rules 2. **Divergent Thinking Phase** ({{time_limit_minus_5}} minutes) - Generate as many {{#ideas}}ideas{{/ideas}}{{#solutions}}potential solutions{{/solutions}}{{#pros_cons}}pros and cons{{/pros_cons}} as possible - Encourage wild and creative thinking - No judgment or criticism during this phase - Build on others' ideas when applicable 3. **Convergent Thinking Phase** (5 minutes) - Group similar {{#ideas}}ideas{{/ideas}}{{#solutions}}solutions{{/solutions}}{{#pros_cons}}points{{/pros_cons}} - Evaluate and prioritize - Look for patterns and connections - Select most promising options 4. **Action Planning (2-3 minutes)** - Identify next steps - Assign responsibilities if applicable - Set follow-up timeline {{#ideas}} Focus on quantity over quality initially. Use techniques like: - Word association - Mind mapping - SCAMPER (Substitute, Combine, Adapt, Modify, Put to other uses, Eliminate, Reverse) - Random word stimulation {{/ideas}} {{#solutions}} Focus on practical and innovative approaches: - Break the problem into smaller parts - Consider analogies from different domains - Think about first principles - Challenge assumptions {{/solutions}} {{#pros_cons}} Create balanced columns for advantages and disadvantages: - Consider short-term and long-term effects - Think about different stakeholders - Evaluate feasibility and resources needed {{/pros_cons}} Please provide specific facilitation techniques and keep the energy high throughout the session!"""; // Add computed value for time limit var builder = new VariantBuilder (new VariantType ("a{sv}")); // Copy all existing arguments var iter = arguments.iterator (); string key; Variant value; while (iter.next ("{sv}", out key, out value)) { builder.add ("{sv}", key, value); } // Add computed value builder.add ("{sv}", "time_limit_minus_5", new Variant.int32 (time_limit - 5)); var modified_args = builder.end (); messages.add (create_user_message (template, modified_args)); return messages; } /** * Gets a string argument from the arguments object. */ private string? get_string_arg_variant (GLib.Variant arguments, string name, string? default_value = null) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("s")).get_string (); } return default_value; } /** * Gets an integer argument from the arguments object. */ private int get_int_arg_variant (GLib.Variant arguments, string name, int default_value = 0) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("i")).get_int32 (); } return default_value; } } /** * Interview prompt template. */ public class InterviewPrompt : Mcp.Prompts.BaseTemplate { /** * Creates a new InterviewPrompt. */ public InterviewPrompt () { base ("interview", "Interview", "Generates interview questions for different contexts"); // Add arguments add_argument ("role", "Role", "Position being interviewed for", true); add_argument ("interview_type", "Type", "Type of interview (technical, behavioral, case_study, situational)", false); add_argument ("experience_level", "Experience Level", "Target experience level (junior, mid, senior, lead)", false); add_argument ("duration", "Duration", "Interview duration in minutes", false); add_argument ("company", "Company", "Company or organization name", false); } /** * {@inheritDoc} */ protected override Gee.ArrayList generate_messages (GLib.Variant arguments) { var messages = new Gee.ArrayList (); string role = get_string_arg_variant (arguments, "role"); string? interview_type = get_string_arg_variant (arguments, "interview_type", "technical"); string? experience_level = get_string_arg_variant (arguments, "experience_level", "mid"); int? duration = get_int_arg_variant (arguments, "duration", 60); string? company = get_string_arg_variant (arguments, "company", null); string template = """Generate a comprehensive interview plan for a {{experience_level}} {{role}} position at {{#company}}{{company}}{{/company}}{{^company}}the company{{/company}}. **Interview Details:** - Type: {{interview_type}} interview - Duration: {{duration}} minutes - Experience Level: {{experience_level}} Please create an interview structure that includes: 1. **Introduction & Ice Breakers** (5 minutes) - Welcome and introduction - Brief company/role overview - Comfort-building questions 2. **Experience & Background** (10-15 minutes) - Previous relevant experience - Technical skills and competencies - Project highlights and achievements - Career motivation and goals 3. **{{#technical}}Technical Assessment{{/technical}}{{#behavioral}}Behavioral Questions{{/behavioral}}{{#case_study}}Case Study{{/case_study}}{{#situational}}Situational Questions{{/situational}}** (20-30 minutes) {{#technical}} - Technical skills assessment - Problem-solving scenarios - Code review or system design - Technology stack questions - Best practices and patterns {{/technical}} {{#behavioral}} - Teamwork and collaboration examples - Conflict resolution - Leadership and initiative - Time management and prioritization - Dealing with failure or setbacks {{/behavioral}} {{#case_study}} - Real-world problem scenarios - Analytical thinking assessment - Decision-making process - Strategic thinking - Business impact consideration {{/case_study}} {{#situational}} - "What would you do if..." scenarios - Priority handling - Ethical dilemmas - Customer/client situations - Pressure and deadline situations {{/situational}} 4. **Candidate Questions** (10-15 minutes) - Questions about the role, team, and company - Growth and development opportunities - Company culture and values - Next steps and timeline 5. **Closing** (5 minutes) - Summary and next steps - Final questions from candidate - Clear communication of follow-up process For each section, provide: - Specific questions to ask - What to look for in answers - Red flags to watch for - Evaluation criteria Tailor the difficulty and depth of questions appropriately for a {{experience_level}} level candidate."""; // Add conditional values var builder = new VariantBuilder (new VariantType ("a{sv}")); // Copy all existing arguments var iter = arguments.iterator (); string key; Variant value; while (iter.next ("{sv}", out key, out value)) { builder.add ("{sv}", key, value); } // Add conditional values builder.add ("{sv}", "technical", new Variant.boolean (interview_type == "technical")); builder.add ("{sv}", "behavioral", new Variant.boolean (interview_type == "behavioral")); builder.add ("{sv}", "case_study", new Variant.boolean (interview_type == "case_study")); builder.add ("{sv}", "situational", new Variant.boolean (interview_type == "situational")); var modified_args = builder.end (); messages.add (create_user_message (template, modified_args)); return messages; } /** * Gets a string argument from the arguments object. */ private string? get_string_arg_variant (GLib.Variant arguments, string name, string? default_value = null) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("s")).get_string (); } return default_value; } /** * Gets an integer argument from the arguments object. */ private int get_int_arg_variant (GLib.Variant arguments, string name, int default_value = 0) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("i")).get_int32 (); } return default_value; } } /** * Story writing prompt template. */ public class StoryWritingPrompt : Mcp.Prompts.BaseTemplate { /** * Creates a new StoryWritingPrompt. */ public StoryWritingPrompt () { base ("story_writing", "Story Writing", "Generates creative writing prompts and story structure guidance"); // Add arguments add_argument ("genre", "Genre", "Story genre (fantasy, scifi, mystery, romance, thriller, horror, literary)", false); add_argument ("theme", "Theme", "Central theme or message", false); add_argument ("setting", "Setting", "Time and place of the story", false); add_argument ("characters", "Characters", "Brief character descriptions", false); add_argument ("plot_point", "Plot Point", "Starting plot point or inciting incident", false); add_argument ("story_length", "Story Length", "Target length (flash, short, novella, novel)", false); add_argument ("audience", "Audience", "Target audience (children, ya, adult)", false); } /** * {@inheritDoc} */ protected override Gee.ArrayList generate_messages (GLib.Variant arguments) { var messages = new Gee.ArrayList (); string? genre = get_string_arg_variant (arguments, "genre", "general"); string? theme = get_string_arg_variant (arguments, "theme", null); string? setting = get_string_arg_variant (arguments, "setting", null); string? characters = get_string_arg_variant (arguments, "characters", null); string? plot_point = get_string_arg_variant (arguments, "plot_point", null); string? story_length = get_string_arg_variant (arguments, "story_length", "short"); string? audience = get_string_arg_variant (arguments, "audience", "adult"); string template = """Generate a comprehensive story writing guide for a {{genre}} story. **Story Parameters:** {{#theme}}Theme: {{theme}}{{/theme}} {{#setting}}Setting: {{setting}}{{/setting}} {{#characters}}Characters: {{characters}}{{/characters}} {{#plot_point}}Plot Point: {{plot_point}}{{/plot_point}} Target Length: {{story_length}} Target Audience: {{audience}} Please provide a structured story guide that includes: 1. **Story Structure Outline** - Three-act structure or hero's journey framework - Key plot points and turning points - Character arcs and development - Pacing recommendations for {{story_length}} fiction 2. **{{genre}} Genre Conventions** - Tropes and expectations for {{genre}} stories - How to innovate within the genre - Reader satisfaction elements - Common pitfalls to avoid 3. **Character Development Guidance** {{#characters}} - How to develop the specified characters - Character voice and dialogue tips - Relationship dynamics {{/characters}} {{^characters}} - Creating compelling original characters - Protagonist and antagonist development - Supporting cast considerations {{/characters}} 4. **World-Building Elements** {{#setting}} - How to bring the setting to life - Sensory details and atmosphere - Integrating setting with plot {{/setting}} {{^setting}} - Creating immersive original worlds - Balancing description with action - Consistency considerations {{/setting}} 5. **Writing Style & Voice** - Narrative perspective recommendations - Tense and POV consistency - Dialogue vs. narration balance - Pacing for {{story_length}} fiction 6. **{{theme}}Theme Integration** - Weaving {{theme}} naturally into the narrative - Symbolism and metaphor opportunities - Avoiding heavy-handed messaging - Subtle thematic reinforcement 7. **Target Audience Considerations** - Age-appropriate content and complexity - Themes and topics suitable for {{audience}} readers - Reading level and vocabulary - Cultural sensitivity and inclusivity 8. **Writing Process & Tips** - Daily word count goals - Overcoming writer's block - Revision and editing strategies - Getting feedback and improving Please provide specific, actionable advice that will help the writer create a compelling {{genre}} story that resonates with {{audience}} readers."""; // Add conditional values var builder = new VariantBuilder (new VariantType ("a{sv}")); // Copy all existing arguments var iter = arguments.iterator (); string key; Variant value; while (iter.next ("{sv}", out key, out value)) { builder.add ("{sv}", key, value); } var modified_args = builder.end (); messages.add (create_user_message (template, modified_args)); return messages; } /** * Gets a string argument from the arguments object. */ private string? get_string_arg_variant (GLib.Variant arguments, string name, string? default_value = null) { if (arguments.lookup_value (name, null) != null) { return arguments.lookup_value (name, new VariantType ("s")).get_string (); } return default_value; } } /** * Main function. * * @param args Command line arguments * @return Exit code */ public static int main (string[] args) { // Create and run the server var server = new ChatServer (); // Handle Ctrl+C to gracefully shutdown // For now, we'll skip signal handling to get the build working var loop = new MainLoop (); // Run the server server.run.begin ((obj, res) => { loop.quit (); }); // Keep the main loop running loop.run (); return 0; }