diff --git a/qiskit-code-assistant-mcp-server/src/qiskit_code_assistant_mcp_server/server.py b/qiskit-code-assistant-mcp-server/src/qiskit_code_assistant_mcp_server/server.py index 7234139..c6734c1 100644 --- a/qiskit-code-assistant-mcp-server/src/qiskit_code_assistant_mcp_server/server.py +++ b/qiskit-code-assistant-mcp-server/src/qiskit_code_assistant_mcp_server/server.py @@ -200,6 +200,49 @@ async def accept_completion_tool(completion_id: str) -> dict[str, Any]: return await accept_completion(completion_id) +################################################## +## MCP Prompts +## - https://modelcontextprotocol.io/docs/concepts/prompts +################################################## + + +@mcp.prompt() +def generate_qiskit_code(task: str) -> str: + """Generate Qiskit Python code for a quantum computing task.""" + return ( + f"Generate Qiskit code for: '{task}'. " + f"1) Call get_completion_tool with prompt='{task}' to generate the code, " + "2) Display the generated code from the response, " + "3) If the user confirms the code is useful, call accept_completion_tool " + "with the completion_id from the response." + ) + + +@mcp.prompt() +def explain_qiskit_concept(concept: str) -> str: + """Explain a Qiskit or quantum computing concept using the knowledge base.""" + return ( + f"Explain '{concept}' using the Qiskit Code Assistant knowledge base: " + f"Call get_rag_completion_tool with prompt='{concept}' and present the " + "explanation from the response. If the answer is helpful, call " + "accept_completion_tool with the completion_id." + ) + + +@mcp.prompt() +def setup_model(model_id: str) -> str: + """Set up a Qiskit Code Assistant model by reviewing its info and accepting the disclaimer.""" + return ( + f"Set up model '{model_id}' for use: " + f"1) Read the qca://model/{model_id} resource to get model details, " + f"2) Read the qca://disclaimer/{model_id} resource to get the disclaimer, " + "3) If a disclaimer is present, show it to the user and call " + f"accept_model_disclaimer_tool with model_id='{model_id}' and the " + "disclaimer_id from the response, " + "4) Confirm the model is ready for use." + ) + + if __name__ == "__main__": import atexit diff --git a/qiskit-code-assistant-mcp-server/tests/test_integration.py b/qiskit-code-assistant-mcp-server/tests/test_integration.py index 141d822..8350f21 100644 --- a/qiskit-code-assistant-mcp-server/tests/test_integration.py +++ b/qiskit-code-assistant-mcp-server/tests/test_integration.py @@ -234,4 +234,39 @@ async def test_disclaimer_workflow(self, mock_env_vars, mock_http_responses): assert accept_result["status"] == "success" +class TestServerRegistration: + """Test that prompts and resource templates are registered.""" + + def test_prompts_registered(self): + """Test that all expected prompts are registered.""" + prompt_names = set(mcp._prompt_manager._prompts.keys()) + expected_prompts = { + "generate_qiskit_code", + "explain_qiskit_concept", + "setup_model", + } + assert expected_prompts.issubset(prompt_names), ( + f"Missing prompts: {expected_prompts - prompt_names}" + ) + + def test_prompt_count(self): + """Test the expected number of prompts.""" + assert len(mcp._prompt_manager._prompts) == 3 + + def test_resource_templates_registered(self): + """Test that all expected resource templates are registered.""" + template_uris = set(mcp._resource_manager._templates.keys()) + expected_templates = { + "qca://model/{model_id}", + "qca://disclaimer/{model_id}", + } + assert expected_templates.issubset(template_uris), ( + f"Missing resource templates: {expected_templates - template_uris}" + ) + + def test_resource_template_count(self): + """Test the expected number of resource templates.""" + assert len(mcp._resource_manager._templates) == 2 + + # Assisted by watsonx Code Assistant