The LLM uses MCP to learn what tools the server makes available; the LLM decides when to use them. (The process is a little more complicated than that, but if you're just trying to call tools without an LLM, those parts aren't really important.) If you ask the LLM, "Find all files with an asterisk," it might deduce that it can use the search_files tool provided by that MCP to gain the needed context, invoke that tool, then process the results it returns. As an engineer, you can just call search_files if you know that's what you want.
Yeah MCP isn't really doing a whole lot. You can give an LLM a generic HTTP extension. Then list a series of GET/POST/PUT and ask it to form the calls and parse the response. The problem is its not really ideal as the calls aren't natural language and its common for it to misguess the next token and mess up things like the route, body, headers, with a hallucination. So people started shortening these calls to simple things like read_file, etc. Prior to MCP there was a ton of playgrounds doing this with simple Playwright functions.
The thing that surprises me is with MCP we have shirked all of the existing tools around OpenAPI specs, OIDC, etc. We could have created a system where all 'services' expose a mcp.slack.com/definition endpoint or something that spit back a list of shortcut terms like send_message and a translation function that composes it into the correct HTTP API (what most MCP servers do). For security we could have had the LLM establish its identity via all our existing systems like OIDC that combine authentication and authorization.
In the system above you would not "install an mcp package" as in a code repo or server. Instead you would allow your LLM to access slack, it would then prompt you to login via OIDC and establish your identity and access level. Then it would grab the OpenAPI spec (machine readable) and the LLM focused shortcuts 'send_message', 'read_message', etc. LLM composes 'send_message Hello World' -> translates to HTTP POST slack.com/message or whatever and bob's your uncle.
If you wanted to do fancy stuff with local systems then you could still build your own server the same way we have all built HTTP servers for decades and just expose the mcp.whatever.com subdomain for discovery. Then skip OIDC or allow ALL or something to simplify if you want.
That's my understanding as well, but you'll be missing the discovery part. You'll have to hardcode the API, at which point you may as well just use the computer API the MCP also uses under the hood.
getting the LLM to use your tool is actually tougher than it should be. You don't get to decide that deterministically.
I don't get what benefit there would be to build an MCP server without an LLM-based agent. You might as well build an API and get the value from a strict, predictable interface & results.
Have a look at the Filesystem example MCP server - https://github.com/modelcontextprotocol/servers/blob/main/sr.... It has a collection of Tools - read_file, read_multiple_files, write_file, etc.
The LLM uses MCP to learn what tools the server makes available; the LLM decides when to use them. (The process is a little more complicated than that, but if you're just trying to call tools without an LLM, those parts aren't really important.) If you ask the LLM, "Find all files with an asterisk," it might deduce that it can use the search_files tool provided by that MCP to gain the needed context, invoke that tool, then process the results it returns. As an engineer, you can just call search_files if you know that's what you want.