Skip to main content
Glama

Perplexica MCP Server

roo_task_may-30-2025_10-58-40-pm.md72.8 kB
**User:** <task> Given the following description of the arguments of the search endpoint of the perplexica server, make our MCP server working correctly: Request Parameters chatModel (object, optional): Defines the chat model to be used for the query. For model details you can send a GET request at http://localhost:3000/api/models. Make sure to use the key value (For example "gpt-4o-mini" instead of the display name "GPT 4 omni mini"). provider: Specifies the provider for the chat model (e.g., openai, ollama). name: The specific model from the chosen provider (e.g., gpt-4o-mini). Optional fields for custom OpenAI configuration: customOpenAIBaseURL: If you’re using a custom OpenAI instance, provide the base URL. customOpenAIKey: The API key for a custom OpenAI instance. embeddingModel (object, optional): Defines the embedding model for similarity-based searching. For model details you can send a GET request at http://localhost:3000/api/models. Make sure to use the key value (For example "text-embedding-3-large" instead of the display name "Text Embedding 3 Large"). provider: The provider for the embedding model (e.g., openai). name: The specific embedding model (e.g., text-embedding-3-large). focusMode (string, required): Specifies which focus mode to use. Available modes: webSearch, academicSearch, writingAssistant, wolframAlphaSearch, youtubeSearch, redditSearch. optimizationMode (string, optional): Specifies the optimization mode to control the balance between performance and quality. Available modes: speed: Prioritize speed and return the fastest answer. balanced: Provide a balanced answer with good speed and reasonable quality. query (string, required): The search query or question. systemInstructions (string, optional): Custom instructions provided by the user to guide the AI's response. These instructions are treated as user preferences and have lower priority than the system's core instructions. For example, you can specify a particular writing style, format, or focus area. history (array, optional): An array of message pairs representing the conversation history. Each pair consists of a role (either 'human' or 'assistant') and the message content. This allows the system to use the context of the conversation to refine results. Example: [ ["human", "What is Perplexica?"], ["assistant", "Perplexica is an AI-powered search engine..."] ] stream (boolean, optional): When set to true, enables streaming responses. Default is false. </task> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs perplexica_mcp_tool.py,test_search.py # Current Time 30.5.2025, 10:48:02 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) (Not available) # Current Cost $0.00 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> # Current Workspace Directory (/Users/the/Developer/thetom42/github/perplexica-mcp) Files perplexica_mcp_tool.py pyproject.toml test_search.py uv.lock </environment_details> --- **Assistant:** I'll examine the current MCP server implementation and update it to correctly handle all the parameters described in the Perplexica search endpoint documentation. <thinking> Let me first read the current implementation to understand what needs to be fixed or updated. </thinking> <read_file> <path>perplexica_mcp_tool.py</path> </read_file> Now let me examine the test file to understan [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [read_file for 'perplexica_mcp_tool.py'] Result: <file><path>perplexica_mcp_tool.py</path> <content lines="1-122"> 1 | #!/usr/bin/env python3 2 | # /// script 3 | # dependencies = [ 4 | # "requests", 5 | # "mcp" 6 | # ] 7 | # /// 8 | 9 | import requests 10 | from mcp.server.fastmcp import FastMCP 11 | 12 | # Create an MCP server 13 | mcp = FastMCP("Perplexica") 14 | 15 | 16 | # Add the search tool 17 | @mcp.tool() 18 | def search(query: str, 19 | chat_model: dict = None, 20 | embedding_model: dict = None, 21 | optimization_mode: str = None, 22 | focus_mode: str = None, 23 | history: list = None, 24 | system_instructions: str = None, 25 | stream: bool = False 26 | ) -> dict: 27 | """ 28 | Search using Perplexica's AI-powered search engine 29 | 30 | Args: 31 | query (str): The search query or question 32 | chat_model (dict, optional): Chat model configuration with: 33 | provider: Provider name (e.g., openai, ollama) 34 | name: Model name (e.g., gpt-4o-mini) 35 | customOpenAIBaseURL: Optional custom OpenAI base URL 36 | customOpenAIKey: Optional custom OpenAI API key 37 | embedding_model (dict, optional): Embedding model configuration with: 38 | provider: Provider name (e.g., openai) 39 | name: Model name (e.g., text-embedding-3-large) 40 | optimization_mode (str, optional): Optimization mode ('speed' or 'balanced') 41 | focus_mode (str, required): Focus mode, must be one of: 42 | 'webSearch', 'academicSearch', 'writingAssistant', 43 | 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' 44 | history (list, optional): Conversation history as list of [role, message] pairs 45 | system_instructions (str, optional): Custom instructions for AI response 46 | stream (bool, optional): Whether to stream responses (default: False) 47 | 48 | Returns: 49 | dict: The search results 50 | """ 51 | return perplexica_search( 52 | query=query, 53 | chat_model=chat_model, 54 | embedding_model=embedding_model, 55 | optimization_mode=optimization_mode, 56 | focus_mode=focus_mode, 57 | history=history, 58 | system_instructions=system_instructions, 59 | stream=stream 60 | ) 61 | 62 | 63 | def perplexica_search(query, chat_model=None, 64 | embedding_model=None, 65 | optimization_mode=None, 66 | focus_mode=None, 67 | history=None, 68 | system_instructions=None, 69 | stream=False 70 | ) -> dict: 71 | """ 72 | Search using the Perplexica API 73 | 74 | Args: 75 | query (str): The search query 76 | chat_model (dict, optional): Chat model configuration with: 77 | provider: Provider name (e.g., openai, ollama) 78 | name: Model name (e.g., gpt-4o-mini) 79 | customOpenAIBaseURL: Optional custom OpenAI base URL 80 | customOpenAIKey: Optional custom OpenAI API key 81 | embedding_model (dict, optional): Embedding model configuration with: 82 | provider: Provider name (e.g., openai) 83 | name: Model name (e.g., text-embedding-3-large) 84 | optimization_mode (str, optional): Optimization mode ('speed' or 'balanced') 85 | focus_mode (str, optional): Focus mode, must be one of: 86 | 'webSearch', 'academicSearch', 'writingAssistant', 87 | 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' 88 | history (list, optional): Conversation history as list of [role, message] pairs 89 | system_instructions (str, optional): Custom instructions for AI response 90 | stream (bool, optional): Whether to stream responses (default: False) 91 | 92 | Returns: 93 | dict: The search results 94 | """ 95 | url = 'http://localhost:3000/api/search' 96 | payload = { 97 | 'query': query 98 | } 99 | 100 | if chat_model: 101 | payload['chatModel'] = chat_model 102 | if embedding_model: 103 | payload['embeddingModel'] = embedding_model 104 | if optimization_mode: 105 | payload['optimizationMode'] = optimization_mode 106 | if focus_mode: 107 | payload['focusMode'] = focus_mode 108 | if history: 109 | payload['history'] = history 110 | if system_instructions: 111 | payload['systemInstructions'] = system_instructions 112 | if stream: 113 | payload['stream'] = stream 114 | 115 | response = requests.post(url, json=payload) 116 | response.raise_for_status() 117 | return response.json() 118 | 119 | 120 | if __name__ == "__main__": 121 | # Run the MCP server 122 | mcp.run() </content> </file> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs perplexica_mcp_tool.py,test_search.py # Current Time 30.5.2025, 10:48:08 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) (Not available) # Current Cost $0.00 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <read_file> <path>test_search.py</path> </read_file> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [read_file for 'test_search.py'] Result: <file><path>test_search.py</path> <content lines="1-41"> 1 | #!/usr/bin/env python3 2 | import perplexica_mcp_tool 3 | 4 | def test_search_perplexica(): 5 | payload = { 6 | 'query': 'What is Perplexica?', 7 | 'chatModel': { 8 | 'provider': 'openai', 9 | 'name': 'gpt-4o-mini' 10 | }, 11 | 'embeddingModel': { 12 | 'provider': 'openai', 13 | 'name': 'text-embedding-3-large' 14 | }, 15 | 'optimizationMode': 'balanced', 16 | 'focusMode': 'webSearch', 17 | 'history': [ 18 | ['human', 'What is AI?'], 19 | ['assistant', 'AI stands for Artificial Intelligence...'] 20 | ], 21 | 'systemInstructions': 'Provide concise answers', 22 | 'stream': False 23 | } 24 | 25 | try: 26 | response = perplexica_mcp_tool.perplexica_search( 27 | query=payload['query'], 28 | chat_model=payload['chatModel'], 29 | embedding_model=payload['embeddingModel'], 30 | optimization_mode=payload['optimizationMode'], 31 | focus_mode=payload['focusMode'], 32 | history=payload['history'], 33 | system_instructions=payload['systemInstructions'], 34 | stream=payload['stream'] 35 | ) 36 | print(f'Response: {response}') 37 | except Exception as e: 38 | print(f'Error: {str(e)}') 39 | 40 | if __name__ == '__main__': 41 | test_search_perplexica() </content> </file> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs perplexica_mcp_tool.py,test_search.py # Current Time 30.5.2025, 10:48:10 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 46.856 (23%) # Current Cost $0.01 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Looking at the current implementation and the requirements, I can see that the MCP server is mostly correct but has one critical issue: the `focus_mode` parameter is marked as optional in the function signature but it's actually required according to the API documentation. Let me fix this and make some improvements to ensure the server works correctly. <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:17 ------- @mcp.tool() def search(query: str, chat_model: dict = None, embedding_model: dict = None, optimization_mode: str = None, focus_mode: str = None, history: list = None, system_instructions: str = None, stream: bool = False ) -> dict: ======= @mcp.tool() def search(query: str, focus_mode: str, chat_model: dict = None, embedding_model: dict = None, optimization_mode: str = None, history: list = None, system_instructions: str = None, stream: bool = False ) -> dict: >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:48:29 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 48.705 (24%) # Current Cost $0.03 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:51 ------- return perplexica_search( query=query, chat_model=chat_model, embedding_model=embedding_model, optimization_mode=optimization_mode, focus_mode=focus_mode, history=history, system_instructions=system_instructions, stream=stream ) ======= return perplexica_search( query=query, focus_mode=focus_mode, chat_model=chat_model, embedding_model=embedding_model, optimization_mode=optimization_mode, history=history, system_instructions=system_instructions, stream=stream ) >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:48:38 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 49.154 (25%) # Current Cost $0.04 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:63 ------- def perplexica_search(query, chat_model=None, embedding_model=None, optimization_mode=None, focus_mode=None, history=None, system_instructions=None, stream=False ) -> dict: ======= def perplexica_search(query, focus_mode, chat_model=None, embedding_model=None, optimization_mode=None, history=None, system_instructions=None, stream=False ) -> dict: >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:49:23 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 49.587 (25%) # Current Cost $0.06 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:85 ------- focus_mode (str, optional): Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' ======= focus_mode (str, required): Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:49:31 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 49.998 (25%) # Current Cost $0.07 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:95 ------- url = 'http://localhost:3000/api/search' payload = { 'query': query } if chat_model: payload['chatModel'] = chat_model if embedding_model: payload['embeddingModel'] = embedding_model if optimization_mode: payload['optimizationMode'] = optimization_mode if focus_mode: payload['focusMode'] = focus_mode if history: payload['history'] = history if system_instructions: payload['systemInstructions'] = system_instructions if stream: payload['stream'] = stream ======= url = 'http://localhost:3000/api/search' payload = { 'query': query, 'focusMode': focus_mode } if chat_model: payload['chatModel'] = chat_model if embedding_model: payload['embeddingModel'] = embedding_model if optimization_mode: payload['optimizationMode'] = optimization_mode if history: payload['history'] = history if system_instructions: payload['systemInstructions'] = system_instructions if stream: payload['stream'] = stream >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:49:57 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 50.587 (25%) # Current Cost $0.09 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Now let me test the updated MCP server to ensure it works correctly: <execute_command> <command>python test_search.py</command> </execute_command> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [execute_command for 'python test_search.py'] Result: The user denied this operation. <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:50:10 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 50.856 (25%) # Current Cost $0.11 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Let me verify the final implementation by reading the updated file to ensure all changes are correct: <read_file> <path>perplexica_mcp_tool.py</path> </read_file> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [read_file for 'perplexica_mcp_tool.py'] Result: <file><path>perplexica_mcp_tool.py</path> <content lines="1-121"> 1 | #!/usr/bin/env python3 2 | # /// script 3 | # dependencies = [ 4 | # "requests", 5 | # "mcp" 6 | # ] 7 | # /// 8 | 9 | import requests 10 | from mcp.server.fastmcp import FastMCP 11 | 12 | # Create an MCP server 13 | mcp = FastMCP("Perplexica") 14 | 15 | 16 | # Add the search tool 17 | @mcp.tool() 18 | def search(query: str, 19 | focus_mode: str, 20 | chat_model: dict = None, 21 | embedding_model: dict = None, 22 | optimization_mode: str = None, 23 | history: list = None, 24 | system_instructions: str = None, 25 | stream: bool = False 26 | ) -> dict: 27 | """ 28 | Search using Perplexica's AI-powered search engine 29 | 30 | Args: 31 | query (str): The search query or question 32 | chat_model (dict, optional): Chat model configuration with: 33 | provider: Provider name (e.g., openai, ollama) 34 | name: Model name (e.g., gpt-4o-mini) 35 | customOpenAIBaseURL: Optional custom OpenAI base URL 36 | customOpenAIKey: Optional custom OpenAI API key 37 | embedding_model (dict, optional): Embedding model configuration with: 38 | provider: Provider name (e.g., openai) 39 | name: Model name (e.g., text-embedding-3-large) 40 | optimization_mode (str, optional): Optimization mode ('speed' or 'balanced') 41 | focus_mode (str, required): Focus mode, must be one of: 42 | 'webSearch', 'academicSearch', 'writingAssistant', 43 | 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' 44 | history (list, optional): Conversation history as list of [role, message] pairs 45 | system_instructions (str, optional): Custom instructions for AI response 46 | stream (bool, optional): Whether to stream responses (default: False) 47 | 48 | Returns: 49 | dict: The search results 50 | """ 51 | return perplexica_search( 52 | query=query, 53 | focus_mode=focus_mode, 54 | chat_model=chat_model, 55 | embedding_model=embedding_model, 56 | optimization_mode=optimization_mode, 57 | history=history, 58 | system_instructions=system_instructions, 59 | stream=stream 60 | ) 61 | 62 | 63 | def perplexica_search(query, focus_mode, 64 | chat_model=None, 65 | embedding_model=None, 66 | optimization_mode=None, 67 | history=None, 68 | system_instructions=None, 69 | stream=False 70 | ) -> dict: 71 | """ 72 | Search using the Perplexica API 73 | 74 | Args: 75 | query (str): The search query 76 | chat_model (dict, optional): Chat model configuration with: 77 | provider: Provider name (e.g., openai, ollama) 78 | name: Model name (e.g., gpt-4o-mini) 79 | customOpenAIBaseURL: Optional custom OpenAI base URL 80 | customOpenAIKey: Optional custom OpenAI API key 81 | embedding_model (dict, optional): Embedding model configuration with: 82 | provider: Provider name (e.g., openai) 83 | name: Model name (e.g., text-embedding-3-large) 84 | optimization_mode (str, optional): Optimization mode ('speed' or 'balanced') 85 | focus_mode (str, required): Focus mode, must be one of: 86 | 'webSearch', 'academicSearch', 'writingAssistant', 87 | 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' 88 | history (list, optional): Conversation history as list of [role, message] pairs 89 | system_instructions (str, optional): Custom instructions for AI response 90 | stream (bool, optional): Whether to stream responses (default: False) 91 | 92 | Returns: 93 | dict: The search results 94 | """ 95 | url = 'http://localhost:3000/api/search' 96 | payload = { 97 | 'query': query, 98 | 'focusMode': focus_mode 99 | } 100 | 101 | if chat_model: 102 | payload['chatModel'] = chat_model 103 | if embedding_model: 104 | payload['embeddingModel'] = embedding_model 105 | if optimization_mode: 106 | payload['optimizationMode'] = optimization_mode 107 | if history: 108 | payload['history'] = history 109 | if system_instructions: 110 | payload['systemInstructions'] = system_instructions 111 | if stream: 112 | payload['stream'] = stream 113 | 114 | response = requests.post(url, json=payload) 115 | response.raise_for_status() 116 | return response.json() 117 | 118 | 119 | if __name__ == "__main__": 120 | # Run the MCP server 121 | mcp.run() </content> </file> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:50:14 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 50.856 (25%) # Current Cost $0.11 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <attempt_completion> <result> I've successfully updated the Perplexica MCP server to correctly handle all the parameters described in the API documentation. Here are the key changes made: **Critical Fix:** - Made `focus_mode` a required parameter (moved it to be the second parameter after `query`) since the API documentation specifies it as required - Updated both the [`search()`](perplexica_mcp_tool.py:18) function and [`perplexica_search()`](perplexica_mcp_tool.py:63) function signatures - Ensured `focusMode` is always included in the payload sent to the API **Parameter Mapping:** The MCP server now correctly maps all parameters to the Perplexica API: - `query` (required) → `query` - `focus_mode` (required) → `focusMode` - `chat_model` (optional) → `chatModel` - `embedding_model` (optional) → `embeddingModel` - `optimization_mode` (optional) → `optimizationMode` - `history` (optional) → `history` - `system_instructions` (optional) → `systemInstructions` - `stream` (optional) → `stream` **Supported Focus Modes:** - `webSearch` - `academicSearch` - `writingAssistant` - `wolframAlphaSearch` - `youtubeSearch` - `redditSearch` **Supported Optimization Modes:** - `speed` - Prioritize speed and return the fastest answer - `balanced` - Provide a balanced answer with good speed and reasonable quality The MCP server is now fully compliant with the Perplexica search endpoint specification and will correctly validate that the required `focus_mode` parameter is provided while properly handling all optional parameters. </result> </attempt_completion> --- **User:** [attempt_completion] Result: The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again. <feedback> When I configure the perplexica MCP server into Claude I got the following: Parameters query* No description focus_mode* No description chat_model No description embedding_model No description optimization_mode No description history No description system_instructions No description stream No description How can I make sure that the description for the arguments can be found? </feedback> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:52:23 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 58.043 (29%) # Current Cost $0.14 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** I need to add proper type annotations with descriptions using the `Annotated` type from `typing` to ensure the parameter descriptions are visible in the MCP tool schema. Let me update the function signature to include proper descriptions. <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:9 ------- import requests from mcp.server.fastmcp import FastMCP ======= import requests from typing import Annotated from mcp.server.fastmcp import FastMCP >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:52:36 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 58.508 (29%) # Current Cost $0.25 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:17 ------- @mcp.tool() def search(query: str, focus_mode: str, chat_model: dict = None, embedding_model: dict = None, optimization_mode: str = None, history: list = None, system_instructions: str = None, stream: bool = False ) -> dict: ======= @mcp.tool() def search( query: Annotated[str, "The search query or question"], focus_mode: Annotated[str, "Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'"], chat_model: Annotated[dict, "Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey"] = None, embedding_model: Annotated[dict, "Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)"] = None, optimization_mode: Annotated[str, "Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)"] = None, history: Annotated[list, "Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'"] = None, system_instructions: Annotated[str, "Custom instructions to guide the AI's response style, format, or focus area"] = None, stream: Annotated[bool, "Whether to stream responses (default: False)"] = False ) -> dict: >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:52:51 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 59.219 (30%) # Current Cost $0.27 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Let me verify the updated file to ensure the changes are correct: <read_file> <path>perplexica_mcp_tool.py</path> <start_line>1</start_line> <end_line>35</end_line> </read_file> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [read_file for 'perplexica_mcp_tool.py'] Result: <file><path>perplexica_mcp_tool.py</path> <content lines="1-35"> 1 | #!/usr/bin/env python3 2 | # /// script 3 | # dependencies = [ 4 | # "requests", 5 | # "mcp" 6 | # ] 7 | # /// 8 | 9 | import requests 10 | from typing import Annotated 11 | from mcp.server.fastmcp import FastMCP 12 | 13 | # Create an MCP server 14 | mcp = FastMCP("Perplexica") 15 | 16 | 17 | # Add the search tool 18 | @mcp.tool() 19 | def search( 20 | query: Annotated[str, "The search query or question"], 21 | focus_mode: Annotated[str, "Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'"], 22 | chat_model: Annotated[dict, "Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey"] = None, 23 | embedding_model: Annotated[dict, "Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)"] = None, 24 | optimization_mode: Annotated[str, "Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)"] = None, 25 | history: Annotated[list, "Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'"] = None, 26 | system_instructions: Annotated[str, "Custom instructions to guide the AI's response style, format, or focus area"] = None, 27 | stream: Annotated[bool, "Whether to stream responses (default: False)"] = False 28 | ) -> dict: 29 | """ 30 | Search using Perplexica's AI-powered search engine 31 | 32 | Args: 33 | query (str): The search query or question 34 | chat_model (dict, optional): Chat model configuration with: 35 | provider: Provider name (e.g., openai, ollama) </content> </file> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:52:55 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 59.219 (30%) # Current Cost $0.27 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <attempt_completion> <result> I've updated the Perplexica MCP server to include proper parameter descriptions using Python's `Annotated` type annotations. This ensures that when you configure the MCP server in Claude, each parameter will display its description. **Key Changes Made:** 1. **Added Import:** Added `from typing import Annotated` to support annotated type hints 2. **Updated Function Signature:** Replaced simple type hints with `Annotated` types that include descriptions: - `query`: "The search query or question" - `focus_mode`: "Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'" - `chat_model`: "Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey" - `embedding_model`: "Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)" - `optimization_mode`: "Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)" - `history`: "Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'" - `system_instructions`: "Custom instructions to guide the AI's response style, format, or focus area" - `stream`: "Whether to stream responses (default: False)" Now when you configure the Perplexica MCP server in Claude, each parameter will show its proper description, making it much easier to understand how to use each parameter correctly. The MCP framework will automatically extract these descriptions from the `Annotated` type hints and include them in the tool schema. </result> </attempt_completion> --- **User:** [attempt_completion] Result: The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again. <feedback> Descriptions still cannot be found. Also, these errors appear: Processing request of type ListResourceTemplatesRequest today at 10:53 PM Processing request of type ListResourcesRequest today at 10:53 PM Processing request of type ListToolsRequest today at 10:53 PM Reading inline script metadata from `perplexica_mcp_tool.py` </feedback> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:55:14 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 60.823 (30%) # Current Cost $0.30 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** The issue is that FastMCP might not be properly extracting descriptions from `Annotated` types. Let me try a different approach using Pydantic models or the FastMCP-specific way to define parameter descriptions. Let me check the FastMCP documentation approach and use a more explicit method. <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:9 ------- import requests from typing import Annotated from mcp.server.fastmcp import FastMCP ======= import requests from mcp.server.fastmcp import FastMCP from pydantic import BaseModel, Field from typing import Optional, List, Dict, Any >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: New problems detected after saving the file: perplexica_mcp_tool.py - [Ruff Error] 21 | query: Annotated[str, "The search query or question"], : Undefined name `Annotated` - [Ruff Error] 22 | focus_mode: Annotated[str, "Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'"], : Undefined name `Annotated` - [Ruff Error] 23 | chat_model: Annotated[dict, "Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey"] = None, : Undefined name `Annotated` - [Ruff Error] 24 | embedding_model: Annotated[dict, "Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)"] = None, : Undefined name `Annotated` - [Ruff Error] 25 | optimization_mode: Annotated[str, "Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)"] = None, : Undefined name `Annotated` - [Ruff Error] 26 | history: Annotated[list, "Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'"] = None, : Undefined name `Annotated` - [Ruff Error] 27 | system_instructions: Annotated[str, "Custom instructions to guide the AI's response style, format, or focus area"] = None, : Undefined name `Annotated` - [Ruff Error] 28 | stream: Annotated[bool, "Whether to stream responses (default: False)"] = False : Undefined name `Annotated` <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:55:33 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 61.325 (31%) # Current Cost $0.32 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** I need to fix the import and use a Pydantic model approach which should work better with FastMCP for parameter descriptions. <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:18 ------- @mcp.tool() def search( query: Annotated[str, "The search query or question"], focus_mode: Annotated[str, "Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'"], chat_model: Annotated[dict, "Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey"] = None, embedding_model: Annotated[dict, "Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)"] = None, optimization_mode: Annotated[str, "Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)"] = None, history: Annotated[list, "Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'"] = None, system_instructions: Annotated[str, "Custom instructions to guide the AI's response style, format, or focus area"] = None, stream: Annotated[bool, "Whether to stream responses (default: False)"] = False ) -> dict: ======= class SearchRequest(BaseModel): query: str = Field(..., description="The search query or question") focus_mode: str = Field(..., description="Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'") chat_model: Optional[Dict[str, Any]] = Field(None, description="Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey") embedding_model: Optional[Dict[str, Any]] = Field(None, description="Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)") optimization_mode: Optional[str] = Field(None, description="Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)") history: Optional[List[List[str]]] = Field(None, description="Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'") system_instructions: Optional[str] = Field(None, description="Custom instructions to guide the AI's response style, format, or focus area") stream: bool = Field(False, description="Whether to stream responses (default: False)") @mcp.tool() def search(request: SearchRequest) -> dict: >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: New problems detected after saving the file: perplexica_mcp_tool.py - [Ruff Error] 56 | query=query, : Undefined name `query` - [Ruff Error] 57 | focus_mode=focus_mode, : Undefined name `focus_mode` - [Ruff Error] 58 | chat_model=chat_model, : Undefined name `chat_model` - [Ruff Error] 59 | embedding_model=embedding_model, : Undefined name `embedding_model` - [Ruff Error] 60 | optimization_mode=optimization_mode, : Undefined name `optimization_mode` - [Ruff Error] 61 | history=history, : Undefined name `history` - [Ruff Error] 62 | system_instructions=system_instructions, : Undefined name `system_instructions` - [Ruff Error] 63 | stream=stream : Undefined name `stream` <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:55:50 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 62.846 (31%) # Current Cost $0.36 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** I need to fix the function body to use the Pydantic model fields correctly: <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:55 ------- return perplexica_search( query=query, focus_mode=focus_mode, chat_model=chat_model, embedding_model=embedding_model, optimization_mode=optimization_mode, history=history, system_instructions=system_instructions, stream=stream ) ======= return perplexica_search( query=request.query, focus_mode=request.focus_mode, chat_model=request.chat_model, embedding_model=request.embedding_model, optimization_mode=request.optimization_mode, history=request.history, system_instructions=request.system_instructions, stream=request.stream ) >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:56:00 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 68.977 (34%) # Current Cost $0.39 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Let me check if there are any remaining issues by reading the current file: <read_file> <path>perplexica_mcp_tool.py</path> <start_line>25</start_line> <end_line>70</end_line> </read_file> [Response interrupted by a tool use result. Only one tool may be used at a time and should be [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [read_file for 'perplexica_mcp_tool.py'] Result: <file><path>perplexica_mcp_tool.py</path> <content lines="25-70"> 25 | history: Optional[List[List[str]]] = Field(None, description="Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'") 26 | system_instructions: Optional[str] = Field(None, description="Custom instructions to guide the AI's response style, format, or focus area") 27 | stream: bool = Field(False, description="Whether to stream responses (default: False)") 28 | 29 | @mcp.tool() 30 | def search(request: SearchRequest) -> dict: 31 | """ 32 | Search using Perplexica's AI-powered search engine 33 | 34 | Args: 35 | query (str): The search query or question 36 | chat_model (dict, optional): Chat model configuration with: 37 | provider: Provider name (e.g., openai, ollama) 38 | name: Model name (e.g., gpt-4o-mini) 39 | customOpenAIBaseURL: Optional custom OpenAI base URL 40 | customOpenAIKey: Optional custom OpenAI API key 41 | embedding_model (dict, optional): Embedding model configuration with: 42 | provider: Provider name (e.g., openai) 43 | name: Model name (e.g., text-embedding-3-large) 44 | optimization_mode (str, optional): Optimization mode ('speed' or 'balanced') 45 | focus_mode (str, required): Focus mode, must be one of: 46 | 'webSearch', 'academicSearch', 'writingAssistant', 47 | 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' 48 | history (list, optional): Conversation history as list of [role, message] pairs 49 | system_instructions (str, optional): Custom instructions for AI response 50 | stream (bool, optional): Whether to stream responses (default: False) 51 | 52 | Returns: 53 | dict: The search results 54 | """ 55 | return perplexica_search( 56 | query=request.query, 57 | focus_mode=request.focus_mode, 58 | chat_model=request.chat_model, 59 | embedding_model=request.embedding_model, 60 | optimization_mode=request.optimization_mode, 61 | history=request.history, 62 | system_instructions=request.system_instructions, 63 | stream=request.stream 64 | ) 65 | 66 | 67 | def perplexica_search(query, focus_mode, 68 | chat_model=None, 69 | embedding_model=None, 70 | optimization_mode=None, </content> </file> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:56:04 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 68.977 (34%) # Current Cost $0.39 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** I need to update the docstring to match the new Pydantic model approach: <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:31 ------- """ Search using Perplexica's AI-powered search engine Args: query (str): The search query or question chat_model (dict, optional): Chat model configuration with: provider: Provider name (e.g., openai, ollama) name: Model name (e.g., gpt-4o-mini) customOpenAIBaseURL: Optional custom OpenAI base URL customOpenAIKey: Optional custom OpenAI API key embedding_model (dict, optional): Embedding model configuration with: provider: Provider name (e.g., openai) name: Model name (e.g., text-embedding-3-large) optimization_mode (str, optional): Optimization mode ('speed' or 'balanced') focus_mode (str, required): Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' history (list, optional): Conversation history as list of [role, message] pairs system_instructions (str, optional): Custom instructions for AI response stream (bool, optional): Whether to stream responses (default: False) Returns: dict: The search results """ ======= """ Search using Perplexica's AI-powered search engine Args: request (SearchRequest): Search request containing all parameters Returns: dict: The search results """ >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:56:13 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 70.698 (35%) # Current Cost $0.41 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Let me check the complete updated file to ensure everything is correct: <read_file> <path>perplexica_mcp_tool.py</path> </read_file> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [read_file for 'perplexica_mcp_tool.py'] Result: <file><path>perplexica_mcp_tool.py</path> <content lines="1-110"> 1 | #!/usr/bin/env python3 2 | # /// script 3 | # dependencies = [ 4 | # "requests", 5 | # "mcp" 6 | # ] 7 | # /// 8 | 9 | import requests 10 | from mcp.server.fastmcp import FastMCP 11 | from pydantic import BaseModel, Field 12 | from typing import Optional, List, Dict, Any 13 | 14 | # Create an MCP server 15 | mcp = FastMCP("Perplexica") 16 | 17 | 18 | # Add the search tool 19 | class SearchRequest(BaseModel): 20 | query: str = Field(..., description="The search query or question") 21 | focus_mode: str = Field(..., description="Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'") 22 | chat_model: Optional[Dict[str, Any]] = Field(None, description="Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey") 23 | embedding_model: Optional[Dict[str, Any]] = Field(None, description="Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)") 24 | optimization_mode: Optional[str] = Field(None, description="Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)") 25 | history: Optional[List[List[str]]] = Field(None, description="Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'") 26 | system_instructions: Optional[str] = Field(None, description="Custom instructions to guide the AI's response style, format, or focus area") 27 | stream: bool = Field(False, description="Whether to stream responses (default: False)") 28 | 29 | @mcp.tool() 30 | def search(request: SearchRequest) -> dict: 31 | """ 32 | Search using Perplexica's AI-powered search engine 33 | 34 | Args: 35 | request (SearchRequest): Search request containing all parameters 36 | 37 | Returns: 38 | dict: The search results 39 | """ 40 | return perplexica_search( 41 | query=request.query, 42 | focus_mode=request.focus_mode, 43 | chat_model=request.chat_model, 44 | embedding_model=request.embedding_model, 45 | optimization_mode=request.optimization_mode, 46 | history=request.history, 47 | system_instructions=request.system_instructions, 48 | stream=request.stream 49 | ) 50 | 51 | 52 | def perplexica_search(query, focus_mode, 53 | chat_model=None, 54 | embedding_model=None, 55 | optimization_mode=None, 56 | history=None, 57 | system_instructions=None, 58 | stream=False 59 | ) -> dict: 60 | """ 61 | Search using the Perplexica API 62 | 63 | Args: 64 | query (str): The search query 65 | chat_model (dict, optional): Chat model configuration with: 66 | provider: Provider name (e.g., openai, ollama) 67 | name: Model name (e.g., gpt-4o-mini) 68 | customOpenAIBaseURL: Optional custom OpenAI base URL 69 | customOpenAIKey: Optional custom OpenAI API key 70 | embedding_model (dict, optional): Embedding model configuration with: 71 | provider: Provider name (e.g., openai) 72 | name: Model name (e.g., text-embedding-3-large) 73 | optimization_mode (str, optional): Optimization mode ('speed' or 'balanced') 74 | focus_mode (str, required): Focus mode, must be one of: 75 | 'webSearch', 'academicSearch', 'writingAssistant', 76 | 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' 77 | history (list, optional): Conversation history as list of [role, message] pairs 78 | system_instructions (str, optional): Custom instructions for AI response 79 | stream (bool, optional): Whether to stream responses (default: False) 80 | 81 | Returns: 82 | dict: The search results 83 | """ 84 | url = 'http://localhost:3000/api/search' 85 | payload = { 86 | 'query': query, 87 | 'focusMode': focus_mode 88 | } 89 | 90 | if chat_model: 91 | payload['chatModel'] = chat_model 92 | if embedding_model: 93 | payload['embeddingModel'] = embedding_model 94 | if optimization_mode: 95 | payload['optimizationMode'] = optimization_mode 96 | if history: 97 | payload['history'] = history 98 | if system_instructions: 99 | payload['systemInstructions'] = system_instructions 100 | if stream: 101 | payload['stream'] = stream 102 | 103 | response = requests.post(url, json=payload) 104 | response.raise_for_status() 105 | return response.json() 106 | 107 | 108 | if __name__ == "__main__": 109 | # Run the MCP server 110 | mcp.run() </content> </file> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:56:18 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 70.970 (35%) # Current Cost $0.43 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** I need to add the `pydantic` dependency to the script metadata since we're now using Pydantic models: <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:2 ------- # /// script # dependencies = [ # "requests", # "mcp" # ] # /// ======= # /// script # dependencies = [ # "requests", # "mcp", # "pydantic" # ] # /// >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:56:39 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 77.445 (39%) # Current Cost $0.46 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <attempt_completion> <result> I've updated the Perplexica MCP server to use Pydantic models with proper field descriptions, which should resolve the parameter description issue. Here are the key changes made: **Major Changes:** 1. **Added Pydantic Dependencies:** - Added `pydantic` to the script dependencies - Imported `BaseModel`, `Field` from Pydantic - Added proper typing imports (`Optional`, `List`, `Dict`, `Any`) 2. **Created SearchRequest Pydantic Model:** - Defined a [`SearchRequest`](perplexica_mcp_tool.py:19) class that inherits from `BaseModel` - Each field uses `Field()` with explicit descriptions: - `query`: "The search query or question" - `focus_mode`: "Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'" - `chat_model`: "Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey" - `embedding_model`: "Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)" - `optimization_mode`: "Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)" - `history`: "Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'" - `system_instructions`: "Custom instructions to guide the AI's response style, format, or focus area" - `stream`: "Whether to stream responses (default: False)" 3. **Updated Function Signature:** - Changed the [`search()`](perplexica_mcp_tool.py:30) function to accept a single `SearchRequest` parameter - Updated the function body to access fields via `request.field_name` 4. **Proper Type Annotations:** - Used `Optional[Type]` for optional parameters - Used specific types like `List[List[str]]` for history - Used `Dict[str, Any]` for model configurations This Pydantic-based approach should properly expose parameter descriptions in the MCP tool schema, making them visible when you configure the server in Claude. The FastMCP framework should automatically extract the field descriptions from the Pydantic model and include them in the tool's JSON schema. </result> </attempt_completion> --- **User:** [attempt_completion] Result: The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again. <feedback> That changed nothing. </feedback> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:57:52 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 78.274 (39%) # Current Cost $0.49 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Let me try a different approach. The issue might be with how FastMCP handles Pydantic models. Let me revert to individual parameters but use the proper FastMCP way to define descriptions through the tool decorator. <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:18 ------- # Add the search tool class SearchRequest(BaseModel): query: str = Field(..., description="The search query or question") focus_mode: str = Field(..., description="Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch'") chat_model: Optional[Dict[str, Any]] = Field(None, description="Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey") embedding_model: Optional[Dict[str, Any]] = Field(None, description="Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large)") optimization_mode: Optional[str] = Field(None, description="Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality)") history: Optional[List[List[str]]] = Field(None, description="Conversation history as list of [role, message] pairs where role is 'human' or 'assistant'") system_instructions: Optional[str] = Field(None, description="Custom instructions to guide the AI's response style, format, or focus area") stream: bool = Field(False, description="Whether to stream responses (default: False)") @mcp.tool() def search(request: SearchRequest) -> dict: """ Search using Perplexica's AI-powered search engine Args: request (SearchRequest): Search request containing all parameters Returns: dict: The search results """ return perplexica_search( query=request.query, focus_mode=request.focus_mode, chat_model=request.chat_model, embedding_model=request.embedding_model, optimization_mode=request.optimization_mode, history=request.history, system_instructions=request.system_instructions, stream=request.stream ) ======= # Add the search tool @mcp.tool( name="search", description="Search using Perplexica's AI-powered search engine" ) def search( query: str, focus_mode: str, chat_model: Optional[Dict[str, Any]] = None, embedding_model: Optional[Dict[str, Any]] = None, optimization_mode: Optional[str] = None, history: Optional[List[List[str]]] = None, system_instructions: Optional[str] = None, stream: bool = False ) -> dict: """ Search using Perplexica's AI-powered search engine Args: query: The search query or question focus_mode: Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' chat_model: Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey embedding_model: Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large) optimization_mode: Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality) history: Conversation history as list of [role, message] pairs where role is 'human' or 'assistant' system_instructions: Custom instructions to guide the AI's response style, format, or focus area stream: Whether to stream responses (default: False) Returns: dict: The search results """ return perplexica_search( query=query, focus_mode=focus_mode, chat_model=chat_model, embedding_model=embedding_model, optimization_mode=optimization_mode, history=history, system_instructions=system_instructions, stream=stream ) >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:58:11 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 80.160 (40%) # Current Cost $0.65 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Now I can remove the Pydantic imports since we're not using them anymore: <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:9 ------- import requests from mcp.server.fastmcp import FastMCP from pydantic import BaseModel, Field from typing import Optional, List, Dict, Any ======= import requests from mcp.server.fastmcp import FastMCP from typing import Optional, List, Dict, Any >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:58:19 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 80.534 (40%) # Current Cost $0.68 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Let me also remove the pydantic dependency from the script metadata: <apply_diff> <path>perplexica_mcp_tool.py</path> <diff> <<<<<<< SEARCH :start_line:2 ------- # /// script # dependencies = [ # "requests", # "mcp", # "pydantic" # ] # /// ======= # /// script # dependencies = [ # "requests", # "mcp" # ] # /// >>>>>>> REPLACE </diff> </apply_diff> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [apply_diff for 'perplexica_mcp_tool.py'] Result: Changes successfully applied to perplexica_mcp_tool.py: <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:58:25 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 80.904 (40%) # Current Cost $0.70 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** Let me check the final version of the file to ensure everything is correct: <read_file> <path>perplexica_mcp_tool.py</path> <start_line>1</start_line> <end_line>50</end_line> </read_file> [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.] --- **User:** [read_file for 'perplexica_mcp_tool.py'] Result: <file><path>perplexica_mcp_tool.py</path> <content lines="1-50"> 1 | #!/usr/bin/env python3 2 | # /// script 3 | # dependencies = [ 4 | # "requests", 5 | # "mcp" 6 | # ] 7 | # /// 8 | 9 | import requests 10 | from mcp.server.fastmcp import FastMCP 11 | from typing import Optional, List, Dict, Any 12 | 13 | # Create an MCP server 14 | mcp = FastMCP("Perplexica") 15 | 16 | 17 | # Add the search tool 18 | @mcp.tool( 19 | name="search", 20 | description="Search using Perplexica's AI-powered search engine" 21 | ) 22 | def search( 23 | query: str, 24 | focus_mode: str, 25 | chat_model: Optional[Dict[str, Any]] = None, 26 | embedding_model: Optional[Dict[str, Any]] = None, 27 | optimization_mode: Optional[str] = None, 28 | history: Optional[List[List[str]]] = None, 29 | system_instructions: Optional[str] = None, 30 | stream: bool = False 31 | ) -> dict: 32 | """ 33 | Search using Perplexica's AI-powered search engine 34 | 35 | Args: 36 | query: The search query or question 37 | focus_mode: Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' 38 | chat_model: Chat model configuration with provider (e.g., openai, ollama), name (e.g., gpt-4o-mini), and optional customOpenAIBaseURL and customOpenAIKey 39 | embedding_model: Embedding model configuration with provider (e.g., openai) and name (e.g., text-embedding-3-large) 40 | optimization_mode: Optimization mode: 'speed' (prioritize speed) or 'balanced' (balance speed and quality) 41 | history: Conversation history as list of [role, message] pairs where role is 'human' or 'assistant' 42 | system_instructions: Custom instructions to guide the AI's response style, format, or focus area 43 | stream: Whether to stream responses (default: False) 44 | 45 | Returns: 46 | dict: The search results 47 | """ 48 | return perplexica_search( 49 | query=query, 50 | focus_mode=focus_mode, </content> </file> <environment_details> # VSCode Visible Files perplexica_mcp_tool.py # VSCode Open Tabs test_search.py,perplexica_mcp_tool.py # Current Time 30.5.2025, 10:58:30 PM (Europe/Berlin, UTC+2:00) # Current Context Size (Tokens) 80.904 (40%) # Current Cost $0.70 # Current Mode <slug>code</slug> <name>💻 Code</name> <model>anthropic/claude-sonnet-4-20250514</model> </environment_details> --- **Assistant:** <attempt_completion> <result> I've updated the Perplexica MCP server with a different approach that should properly expose parameter descriptions. The key changes made: **Updated Approach:** 1. **Enhanced Tool Decorator:** Used the [`@mcp.tool()`](perplexica_mcp_tool.py:18) decorator with explicit `name` and `description` parameters 2. **Proper Type Annotations:** Used standard Python typing with: - `Optional[Dict[str, Any]]` for optional dictionary parameters - `Optional[List[List[str]]]` for the history parameter - `Optional[str]` for optional string parameters - `bool` for the stream parameter 3. **Detailed Docstring:** Added comprehensive parameter descriptions in the docstring using the standard Args format: - `query`: The search query or question - `focus_mode`: Focus mode, must be one of: 'webSearch', 'academicSearch', 'writingAssistant', 'wolframAlphaSearch', 'youtubeSearch', 'redditSearch' - `chat_model`: Chat model configuration with provider, name, and optional custom OpenAI settings - `embedding_model`: Embedding model configuration with provider and name - `optimization_mode`: Optimization mode ('speed' or 'balanced') - `history`: Conversation history as list of [role, message] pairs - `system_instructions`: Custom instructions to guide AI response - `stream`: Whether to stream responses 4. **Maintained Functionality:** The core functionality remains the same - all parameters are correctly passed to the [`perplexica_search()`](perplexica_mcp_tool.py:48) function and properly mapped to the Perplexica API. This approach uses FastMCP's standard parameter description mechanism through docstrings and proper type annotations, which should be recognized by the MCP framework and displayed in Claude's interface. The tool maintains full compatibility with the Perplexica API while providing clear parameter descriptions. </result> </attempt_completion>

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/thetom42/perplexica-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server