Building Smarter MCP Servers: Generic vs. Domain-Specific Approaches

A presentation at JUG Summer Camp in September 2025 in La Rochelle, France by Horacio Gonzalez

Slide 1

Slide 1

Building Smarter MCP Servers Generic vs. Domain-Specific Approaches Horacio González 2025-09-05

Slide 2

Slide 2

LLM evolution From simple chat to tool-enhanced agent! What’s the weather like in Madrid today? Weather API getWeather(“Madrid (ES)”) Today it is sunny in Madrid, but very cold, take a coat. {“weather”:”sunny”, “temperature”:”1.8ºC”}

Slide 3

Slide 3

LLM are only language models What’s the weather like in Madrid today? I’m unable to provide real-time information or current weather updates. They have no built-in way to use external tools or real-time data

Slide 4

Slide 4

Tools and plugins were added What’s the weather like in Madrid today? Today it is sunny in Madrid, but very cold, take a coat. Weather API getWeather(“Madrid (ES)”) {“weather”:”sunny”, “temperature”:”1.8ºC”} LLM recognizes it needs an external function and calls it, integrating the result into a natural-language response.

Slide 5

Slide 5

LLM don’t call directly those tools What’s the weather like in Madrid today? What’s the weather like in Madrid today? If needed, you have an available weather tool: getWeather(city) Call getWeather(“Madrid”) getWeather(“Madrid”) {“weather”:”sunny”,”temperature”:”1.8ºC”} Result of the tool calling: {“weather”:”sunny”,”temperature”:”1.8ºC”} Today it is sunny in Madrid, but very cold, take a coat. Today it is sunny in Madrid, but very cold, take a coat.

Slide 6

Slide 6

How are those LLM Tools defined? LyingWeatherTool.java //DEPS dev.langchain4j:langchain4j:1.0.0-beta1 import dev.langchain4j.agent.tool.Tool; public class LyingWeatherTool{ @Tool(“A tool to get the current weather in a city”) public static String getWeather(String city) { return “The weather in ” + city + ” is sunny and hot.”; } } Here in Java using LangChain4j

Slide 7

Slide 7

Why this matters? ● Moves LLMs from static text generation ○ dynamic system components ● Increases accuracy & real-world usability ● Allows developers to control what the LLM can access What’s the weather like in Madrid today? Today it is sunny in Madrid, but very cold, take a coat.

Slide 8

Slide 8

From LLM chats to LLM-powered agents Can you summarize this YouTube video? Of course,the video is a talk of Horacio about MCP… *This is a “fake” view, remember LLMs dont call tools directly But it’s the view from the Point of View of the user LLMs act like an agent that can plan actions: search the web, run some code, then answer

Slide 9

Slide 9

The rapid evolution of agents Before MCP (2023–November 2024) ● ● Agents == niche LangChain, bespoke APIs, Copilot experiments… No standard way to connect LLMs to tools. MCP Introduced (Nov 2024) The explosion (2025) ● Anthropic launches Model Context Protocol. ● ● Vendor-neutral, open standard for connecting LLMs. Agents go mainstream: runtimes, orchestration, enterprise adoption. ● MCP reframed as the interoperability layer for agents.

Slide 10

Slide 10

Model Context Protocol (MCP): The missing link MCP bridges LLMs with your applications, enabling controlled, real-world interactions

Slide 11

Slide 11

Why Do We Need MCP? LLM function calling is useful, but it lacks structure

Slide 12

Slide 12

Why Do We Need MCP? Problem ● LLMs don’t automatically know what functions exist. ● No standard way to expose an application’s capabilities. ● Hard to control security and execution flow. ● Expensive and fragile integration spaghetti

Slide 13

Slide 13

Model Context Protocol Anthropic, November 2024: LLMs intelligence isn’t the bottleneck, connectivity is

Slide 14

Slide 14

Model Context Protocol De facto standard for exposing system capabilities to LLMs https://modelcontextprotocol.io/

Slide 15

Slide 15

The MCP Landscape Today Major players adopted MCP: ● Anthropic – Originator and tool provider (Claude Desktop, SDKs). ● OpenAI – Agent SDK, ChatGPT Desktop, Responses API. ● Google DeepMind – Gemini support and tooling. ● Microsoft / GitHub – Copilot Studio, Azure, Office integration, C# SDK. ● Developer Platforms – Replit, JetBrains, Sourcegraph, TheiaIDE. ● Enterprise / Services – Block, Stripe, Cloudflare, Baidu Maps. ● Thousands of MCP servers live.

Slide 16

Slide 16

How MCP works ● Applications define an MCP manifest (structured JSON). ● The manifest describes available functions, input/output formats, and security policies. ● LLMs can discover and request function execution safely. Weather MCP Server

Slide 17

Slide 17

MCP is provider-agnostic Works with any LLM provider Ensures standardized function exposure across platforms

Slide 18

Slide 18

MCP solves integration spaghetti

Slide 19

Slide 19

The architecture of MCP Clients, servers, protocol and transports Tools, resources and prompts

Slide 20

Slide 20

MCP Servers: APIs in natural language A new kind of API

Slide 21

Slide 21

MCP Clients: on the AI assistant or app side One MCP client per MCP Server

Slide 22

Slide 22

MCP Protocol & Transports MCP Protocol Follow the JSON-RPC 2.0 specification MCP Transports ● STDIO (standard I/O) ○ Client and server in the same instance ● HTTP with SSE transport (deprecated) ● Streamable HTTP ○ Servers SHOULD implement proper authentication for all

Slide 23

Slide 23

Full MCP architecture

Slide 24

Slide 24

Services: tools, resources & prompts ● Tools ○ Standardized way to expose functions that can be invoked by clients ● Resources ○ Standardized way to expose resources to clients ○ Each resource is uniquely identified by a URI ● Prompts ○ Standardized way to expose prompt templates to clients ○ Structured messages and instructions for interacting with LLMs

Slide 25

Slide 25

MCPs are APIs And they should be architectured in a similar way

Slide 26

Slide 26

Developer Expectations Have Shifted Winter 2024−2025 ● “What is MCP?” ● “How do I connect my DB?” Summer 2025 ● “How do I build smarter MCP servers?” ● “How do I secure them?” ● “How do they fit into agent workflows?”

Slide 27

Slide 27

Let’s use an example: RAGmonsters https://github.com/LostInBrittany/RAGmonsters

Slide 28

Slide 28

RAGmonsters PostgreSQL Database

Slide 29

Slide 29

We want to allow LLM request it Two options: ● A generic PostgreSQL MCP server ● A custom-made MCP server tailored for RAGmonsters Which one to choose?

Slide 30

Slide 30

Generic PostgreSQL MCP server Using PostgreSQL MCP Server ● A Resource that give the table schema for tables: /schema ● A Tool that allows to do SQL queries: query LLM can know what tables do we have and what is their structure, and it can request them Implementation: https://github.com/CleverCloud/mcp-pg-example PostgreSQL MCP Server: https://github.com/modelcontextprotocol/servers/tree/main/src/postgres

Slide 31

Slide 31

Custom-made RAGmonsters MCP server Coding a MCP server for it. It offers targeted tools: ● getMonsterByName: fetches detailed information about a monster. ● listMonstersByType: Lists monsters of a given type. ● Easy, intuitive interactions for LLMs. ● Optimized for specific use cases. ● Secure (no raw SQL). Implementation: https://github.com/LostInBrittany/RAGmonsters-mcp-pg

Slide 32

Slide 32

How to choose?

Slide 33

Slide 33

But how to do it? Some down-to-Earth, practical advices

Slide 34

Slide 34

Design principles What “good” looks like ● Narrow, named capabilities each tool should read like a product verb: getMonsterByName, listMonstersByType, compareMonsters. ● Stable types in/out explicit schemas (IDs, enums, unions) so the agent can plan reliably. ● Deterministic behavior same inputs → same outputs; include idempotencyKey when making state changes. ● Least privilege tools do one thing; internal queries/side-effects are not exposed. ● Guardrails at the edge validate inputs, clamp result sizes, redact PII, enforce authZ inside the server.

Slide 35

Slide 35

Capability modeling Turn “tasks” into MCP tools/resources/prompts Tools (actions) ● Read: getMonsterByName(name) -> Monster ● List: listMonstersByType(type, limit=25, cursor?) -> {items:[Monster], nextCursor} ● Search: searchMonsters(q, limit=10) -> [MonsterSummary] Resources (documents/URIs the client can browse/fetch) ● ragmonsters://schema/Monster (JSON schema for types) ● ragmonsters://docs/query-tips (compact usage notes) ● ragmonsters://images/{monsterId} (read-only asset stream) Prompts (reusable instructions/templates) ● prompt://ragmonsters/answering-style (tone, do/don’t) ● prompt://ragmonsters/disambiguation (ask for missing fields first)

Slide 36

Slide 36

Input contracts Make the LLM succeed on the first try ● ● ● Refer enums & unions for fields the model tends to invent type ∈ {BEAST, ELEMENTAL, UNDEAD,…} Add optional “reason”/“intent” fields that your server ignores functionally but logs for eval Hard limits at the boundary: limit ≤ 50, name.length ≤ 64, q.length ≤ 120 { “type”: “object”, “required” : [“type”], “properties” : { “type”: {“enum”: [“BEAST”,”ELEMENTAL” ,”UNDEAD”,”CELESTIAL” ,”HUMANOID” ]}, “limit”: {“type”:”integer”,”minimum”:1,”maximum”:50}, “cursor”: {“type”:”string”} } }

Slide 37

Slide 37

Output shape Make it composable Always return a machine part and a human part: ● data: typed payload the client/agent can chain. ● summary: 1–2 lines the model can quote. ● next: cursors or suggested follow-ups. { “data”: { “items”: [ { “id”:”glowfang” , “type”:”BEAST”, “danger”:3 } ], “nextCursor” :”abc123” }, “summary”: “Found 1 beast: Glowfang (danger 3).” , “next”: [“getMonsterByName(‘glowfang’)” ] }

Slide 38

Slide 38

Security & governance Baked into the server ● AuthN: accept a caller token; map to user/roles inside your server. ● AuthZ: per-tool role checks (viewer, editor, admin). ● Data scope: inject row-level filters (tenant, project) before hitting storage. ● Rate limits: e.g., 60 rpm per user; lower for heavy tools. ● Redaction: never return secrets; hash IDs in logs. ● Explainability: include source/policy notes in responses where relevant.

Slide 39

Slide 39

Observability & evaluation From the beginning ● ● ● ● Structured logs {tool, userId, durationMs, ok, errorCode} Traces around datastore calls; record row counts Golden tasks keep a small suite (10–20) of representative prompts; run nightly Safety tests: prompt-injection set, over-broad queries, boundary limits

Slide 40

Slide 40

Conclusion ● Generic MCP servers Quick to set up, flexible, but less efficient and more error-prone. ● Domain-specific MCP servers Safer and faster for targeted tasks, but need more upfront design. Choose wisely Use generic for exploration, domain-specific for production. A bit like for REST APIs, isn’t it?

Slide 41

Slide 41

The road ahead ● MCP is quickly becoming the lingua franca of agents. ● We’re still early — best practices are being shaped right now. ● Your design choices today will set the tone for secure, scalable agent ecosystems tomorrow.

Slide 42

Slide 42

That’s all, folks! Thank you all!