VUFIND-1809: Add Model Context Protocol (MCP) server support#4939
VUFIND-1809: Add Model Context Protocol (MCP) server support#4939maccabeelevine wants to merge 43 commits intovufind-org:dev-12.0from
Conversation
|
This POC doesn't do anything useful yet (check out the amazing addition function), but it is a working MCP server embedded in VuFind. Next step will be to build some real capabilities, i.e. searching and document retrieval. The implementation adapts the SDK's example of Symfony integration as well as the work @demiankatz is doing on #4672. There would be some major dependency roadblocks to actually integrating this into VuFind, as I mentioned on the Jira. This POC uses the official PHP SDK, |
|
Note for testing, I've locally modified the vendor file (yes I know) laminas-servicemanager/src/ServiceManager to make the |
| 'vufind_api' => [ | ||
| 'register_controllers' => [ | ||
| \VuFindApi\Controller\AdminApiController::class, | ||
| // \VuFindApi\Controller\McpController::class, |
There was a problem hiding this comment.
I'm not sure whether this actually belongs in VuFindApi, and if so whether it should be discoverable from the main API endpoint, given the protocol is quite different. To consider.
|
You can test the server in a couple of ways:
either way, hitting a URL like http://localhost:[port]/vufind/api/v1/mcp |
It now does a basic keyword search, and record retrieval by ID. |
To get around this, I've temporarily forked |
module/VuFindApi/src/VuFindApi/Mcp/Capabilities/AbstractSearch.php
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| // $content = json_decode($this->params()->getController()->getRequest()->getContent(), true); | ||
| // $mcpMethod = $content['method'] ?? ''; |
There was a problem hiding this comment.
I have to think through if this is useful. Methods in MCP are not specific enough, i.e. all tools are method "tools/call" and you need a further param "name" to know what's actually being called. But if we go down the route of allowing selective methods/names, then I also have to consider the fact that "tools/list" would list them all. Etc. for resources, prompts, etc. It's probably a good start just to indivisibly allow or disallow MCP. Of course the permissions.ini still lets you narrow down that single permission by IP address, etc.
| protected function outputAuthError(string $messageId): Response | ||
| { | ||
| $error = new Error($messageId, $this->AUTH_ERROR, 'Access denied'); | ||
| $response = $this->getResponse(); |
There was a problem hiding this comment.
Much of this is borrowed from ApiTrait. Not sure if it's worth refactoring that method for the few bits that are useful here.
Forking is no longer necessary, as the upstream |
demiankatz
left a comment
There was a problem hiding this comment.
Thanks, @maccabeelevine, I took a first look through this. I'm not yet familiar with the libraries and technologies being used, so I mainly focused on general design and documentation for this initial pass.
| 'vufind_api' => [ | ||
| 'register_controllers' => [ | ||
| \VuFindApi\Controller\AdminApiController::class, | ||
| // \VuFindApi\Controller\McpController::class, |
module/VuFindApi/src/VuFindApi/Mcp/Capabilities/AbstractSearch.php
Outdated
Show resolved
Hide resolved
module/VuFindApi/src/VuFindApi/Mcp/Capabilities/AbstractSearch.php
Outdated
Show resolved
Hide resolved
module/VuFindApi/src/VuFindApi/Mcp/Capabilities/AbstractSearch.php
Outdated
Show resolved
Hide resolved
|
Hello, @EreMaijala found my hobby project (MCP server for Finna.fi) and mentioned that you are working on MCP support for VuFind. My implementation wraps the VuFind API but prunes and renames fields to make them more LLM-friendly. I've also limited the search options and record fields to improve reliability, though these could be made configurable. Although I built this on a different stack (Cloudflare Workers), it might offer some inspiration. One feature I found useful is a dedicated "help" tool. It provides extra documentation to the model only when requested, saving context space compared to putting everything in the tool description. This could be helpful for web-based clients like ChatGPT/Claude that don't (at least yet) support local agent "skills." Links for reference: A tip for iterating: I've found it helpful to ask the LLM for feedback on the tool spec after it fails a complex task. |
demiankatz
left a comment
There was a problem hiding this comment.
Just took another look at this and have a few minor suggestions and ideas below. (I also see that I previously reviewed this and forgot that I had, so sorry if any of these are repeats from before).
module/VuFindApi/src/VuFindApi/Mcp/Capabilities/AbstractSearch.php
Outdated
Show resolved
Hide resolved
module/VuFindApi/src/VuFindApi/Mcp/Capabilities/AbstractSearch.php
Outdated
Show resolved
Hide resolved
Co-authored-by: Demian Katz <demian.katz@villanova.edu>
affc31f to
d342ac6
Compare
Co-authored-by: Demian Katz <demian.katz@villanova.edu>
Thanks belatedly @samuli for the suggestions! You obviously have some great experience building and iterating on this, seeing how the models react. I have to spend some time considering it all. I love what you did with the tool descriptions. Re: the help text, I understand the intent to save context window space, but I hate to not take advantage of the input schema (defining fields and enums)... have to consider more. I also appreciate the tip on iterating with LLM feedback -- so far Gemini CLI has been pretty reliably using the tools I've built here so far, but I can see how that (and the context window problem) would be trickier as the number of capabilities grows. Can I ask about language choice -- writing all the help text etc. in English? Do the models do a lousy job of interpreting Finnish at this point? Do you anticipate that changing? |
I see what you mean. The spec should include enough information for the model to operate the tools and ideally the help tool is not needed at all for this purpose. But it could be a handy way to provide the model a way to request more info when needed (about tools or something else).
In my experience the frontier models understand and interpret Finnish well (the output might not be 100% natural but that's another issue). Smaller models have worse multilingual skills which is easy to notice from unnatural output but they might still understand the query due to cross-lingual generalization. In other projects I have written the spec in English and included important key terms also in Finnish to make sure that the model understands them. |
1d5e7a4 to
1c8fec6
Compare
Per VUFIND-1809, from https://modelcontextprotocol.io/docs/getting-started/intro
This extends VuFind's existing API capabilities to provide an MCP server, i.e. to respond to MCP queries from AI models.
TODO