vim-ai icon indicating copy to clipboard operation
vim-ai copied to clipboard

Model Context Protocol support

Open Konfekt opened this issue 8 months ago • 9 comments

Model Context Protocol (MCP) is an open protocol introduced by Anthropic that standardizes how large language models communicate with external tools or resources. So >>>mcp would be a standardized generalization of >>>execute/file/... to include other data such as PostgreSQL, Perplexity, Excel, ... (and also manipulate them) by installing one of the linked MCP servers.

Konfekt avatar Apr 06 '25 06:04 Konfekt

Hi, attempting to work on this at https://github.com/kracejic/vim-ai/tree/mcp?tab=readme-ov-file#model-context-protocol-mcp.

Currently supports only stdio and it does not ask for permissions for (some) tools. So for anyone trying this, be careful. You can already add multiple MCP servers.

Problem is it requires mcp python library installed. But I wrote it in a way that if you do not have it, rest of the plugin will still work. MCP python library itself requires to run in the async context, so I am wrapping it in a thread. Its interesting, I am not sure if this is the best way to do it, but it works quite nicely in the end.

Also initialization takes some time, about 1 sec. So I want to investigate keeping the initialized MCP objects per buffer and reinitialize only when json configuration changes.

Code is still a bit rough, but it works in both vim and neovim for me.

@madox2 would you be interested in this as well?

kracejic avatar May 17 '25 20:05 kracejic

The way I currently think of MCP is that implementing it is quite provider specific. It might also require more alignment as it would allow llm to be autonomous to some level and that's another reason I would put this responsibility to the provider. What we could do in vim-ai is to extend provider's interface with some stuff needed to implement MCP, and if needed provide some utils (e.g. for confirmation prompts, etc.).

madox2 avatar May 20 '25 21:05 madox2

I was wondering about the same thing. MCP is quite AI API agnostic, but the function calling itself is probably where the difference is.

I can move the AI+MCP while loop to the provider. Should I put it into the default openai one, or should I make a new repo openai-mcp?

I will need support for <<< tool_call and >>> tool_response aichat segments from the core part of the plugin. I will do it more generic than now. I will dump the content into messages and set the role to tool_call / tool_response and let the provider to convert that into whatever format AI API expects.

For the confirmation... I planned to just stop the loop after <<< tool_call and let the user inspect & run :AIChat again to resume the loop.

I plan to add an option to specify ask/dontask lists to specify confirmation behavior for different tools.

kracejic avatar May 21 '25 17:05 kracejic

I have moved the logic into provider. As a proof of concept, I have added confirmation via new "info" segment which is ignored for the messages (without the info segment it is not obvious what is going on). You can specify options.mcp_dontask or alternatively use options.mcp_ask.

I would maybe also add "dontask" to the mcp json so people can specify it on one place as well.

[chat]
provider=openai
options.temperature=1
options.request_timeout=300
options.model=gpt-4.1-mini
options.max_completion_tokens=10000
options.stream=1
options.mcp=~/bin/mcp/dev.json
options.mcp_dontask=list_directory,directory_tree

>>> user
 
What files are in this folder? And what is in xx.md? do it in one call. Do not forget to tell me about the xx.md.

<<< tool_call

{"role": "assistant", "content": [{"type": "text", "text": ""}], "tool_calls": [{"index": 0, "id": "call_uA0GwpKTWsXMNeuDiFPz6Ct0", "type": "function", "function": {"name": "list_directory", "arguments": "{\"path\": \"./\"}"}}, {"index": 1, "id": "call_VIV1AmWe8i1utUH52hc3Ljci", "type": "function", "function": {"name": "read_file", "arguments": "{\"path\": \"./xx.md\"}"}}]}

<<< info

Tools that require confirmation: {'read_file'}, run :AIChat again to authorize

I still need to optimize the MCP initialization as it still is re-initialized on every :AIChat, which adds annoying ~1sec delay.

kracejic avatar May 21 '25 21:05 kracejic

Great job!

New openai-mcp provider sounds great. One of the reasons for moving mcp logic to the external provider is that I don't want to introduce 3rd party python dependency to the core plugin (there are good reasons for that from the past, it would definitely break some vim environments)

I will need support for <<< tool_call and >>> tool_response aichat segments from the core part of the plugin. I will do it more generic than now. I will dump the content into messages and set the role to tool_call / tool_response and let the provider to convert that into whatever format AI API expect

For the confirmation... I planned to just stop the loop after <<< tool_call and let the user inspect & run :AIChat again to resume the loop.

As a proof of concept, I have added confirmation via new "info" segment which is ignored for the messages

Looks all good!

madox2 avatar May 22 '25 19:05 madox2

Thanks, I enjoy using this plugin and missed these two thing (async chat and mcp), so I want to give back a little.

Important note about the mcp dependency... I though about that, mcp is not "hard" dependency they way I added it. The provider in core plugin still works fine without mcp library if you are not using mcp (by specifying options.mcp path)...

When you do try to use MCP without mcp library installed, you get an error message telling you what is wrong. See example chat:

[chat]
provider=openai
options.temperature=1
options.request_timeout=300
options.model=gpt-4.1-mini
options.max_completion_tokens=10000
options.stream=1
options.mcp=~/bin/mcp/dev.json
options.mcp_dontask=list_directory,directory_tree

>>> user
 
What files are in this folder? And what is in x.md? do it in one call. Do not forget to tell me about the x.md.

<<< error getting response: Python library MCP import has failed, you can't use MCP.

```python
Traceback (most recent call last):
  File "/home/xohnheis/.vim/bundle/vim-ai/py/chat.py", line 138, in run
    for chunk in self.provider.request(self.messages):
                 ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/home/xohnheis/.vim/bundle/vim-ai/py/providers/openai.py", line 80, in request
    mcps.load_cfg(self.options["mcp"])
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/home/xohnheis/.vim/bundle/vim-ai/py/MCP.py", line 162, in load_cfg
    raise Exception("Python library MCP import has failed, you can't use MCP.")
Exception: Python library MCP import has failed, you can't use MCP.

This is the important part:

MCP_import_check = True
try:
    from mcp import ClientSession, StdioServerParameters
    from mcp.client.stdio import stdio_client
except:
    MCP_import_check = False

And then I can work with the MCP_import_check variable and prevent calling anything from the external mcp library.

Let me know if you still want me to put it into its own provider. I do not mind to do it either way.

Both approaches have some problems... Either we put more functionality / bloat to the core plugin. Or I will have to maintain 80% copy of the default provider in a fork. Or I would probably try some tricks with inheritance and try to reuse core openai provider functionality with some tiny tweaks in the core openai provider...

kracejic avatar May 22 '25 20:05 kracejic

I am quite hesitating introducing external dependency even though it's not hard. Many vim installations comes with pre built python and would have no option to set it up. I would like all functionality in the core plugin to work out of the box. So I would say, let's move it to the external provider for now.

madox2 avatar May 23 '25 22:05 madox2

Hi @madox2, understood. I made a pull request with just the support in core plugin that I have needed.

The provider with MCP support (only stdio for next couple of days until I find more time to play with it) is here: https://github.com/kracejic/vim-ai-provider-openai-mcp

kracejic avatar May 24 '25 21:05 kracejic

Needed commit was cherry-picked by @madox2 (thanks!), now https://github.com/kracejic/vim-ai-provider-openai-mcp is usable now as a plugin for vim-ai that gives you mcp functionality (stdio only as of now).

Others can also implement providers implementing plugins for vim-ai with mcp or other tool calling functionality.

kracejic avatar Jul 30 '25 09:07 kracejic