Du har byggt en MCP-server. Verktygen fungerar. Du ansluter en LLM-agent. När du ser den arbeta märker du att den ignorerar verktygen, anropar dem med märkliga parametrar, blir osäker på vilket verktyg den ska använda och kedjar ihop dem i konstiga ordningsföljder.
Detta är gapet mellan ”verktyg som finns” och ”verktyg som LLM-modeller använder rätt”. Här går merparten av arbetet med MCP-servrar till spillo. Företag bygger kraftfulla funktioner, exponerar dem som verktyg och ser sedan LLM-modeller misslyckas med att använda dem effektivt.
Ett användbart perspektivskifte är att betrakta verktygsdesign som UX-design där LLM-modellen är användaren. Verktygsbeskrivningen är användargränssnittet. Schemat är formuläret. Felmeddelandena är återkopplingen. Får du detta rätt arbetar LLM-modeller effektivt. Får du det fel blir din avancerade backend osynlig för agenten.
Artikeln går igenom principerna, med konkreta exempel på vad som fungerar och vad som inte gör det.
Princip 1: Verktygsnamn förmedlar avsikten
Verktygets namn är det första LLM-modellen ser. Det bör beskriva vad verktyget gör, uttryckt som en handling.
Dåligt:
customers(substantiv, ingen handling)process_customer(vagt)do_x(meningslöst)
Bättre:
search_customers(tydlig handling)get_customer_by_id(specifik åtgärd)update_customer_email(specifik ändring)
Varför det spelar roll: LLM-modeller söker igenom verktygslistor efter relevanta verktyg. Ett beskrivande namn gör att de snabbt hittar rätt. Ett vagt namn tvingar dem att läsa beskrivningen noggrant, vilket de inte alltid gör.
Ett användbart mönster är standardiserade verbprefix.
list_*,search_*,get_*för läsning.create_*,update_*,delete_*för skrivning.analyze_*,summarize_*för beräkning.
Konsekvens genom hela servern hjälper LLM-modellen att bygga mentala modeller.
Princip 2: Beskrivningar är prompter
Verktygets beskrivning är den viktigaste texten på servern. LLM-modellen använder den för att avgöra om och hur verktyget ska användas.
Dålig beskrivning:
search_customers: Sök i kunddatabasen.
Bättre beskrivning:
search_customers: Hitta kunder efter namn, e-postadress eller företag. Returnerar upp till 10 matchande kunder med grundläggande information. Använd detta när du behöver identifiera en kund som användaren hänvisar till. Använd i stället get_customer_by_id för exakta sökningar efter ID.
Lägg märke till vad den bättre versionen gör:
- Beskriver indata (”efter namn, e-postadress eller företag”).
- Beskriver utdata (”upp till 10 matchande kunder med grundläggande information”).
- Anger när verktyget ska användas (”när du behöver identifiera en kund som användaren hänvisar till”).
- Anger när verktyget inte ska användas (”Använd i stället get_customer_by_id för exakta sökningar efter ID”).
Delen om när verktyget inte ska användas är avgörande. Utan den kan LLM-modellen anropa search_customers när get_customer_by_id hade passat bättre.
Princip 3: Parameterbeskrivningar spelar roll
Varje parameter behöver en beskrivning. Förlita dig inte enbart på parameterns namn.
Dåligt:
{
customer_id: string,
fields: string[]
}
Bättre:
{
customer_id: string, // "Kundens unika identifierare. Hämta den från search_customers eller från uttryckliga användarindata."
fields: string[] // "Specifika fält som ska returneras. Tillgängliga: name, email, phone, tier, created_at, last_active. Om inget anges returneras name och email."
}
Beskrivningarna:
- Talar om för LLM-modellen hur värdet hämtas.
- Anger tillåtna värden där det är tillämpligt.
- Anger standardvärden.
Princip 4: Fel vägleder återhämtningen
När ett verktyg returnerar ett fel styr felmeddelandet LLM-modellens nästa åtgärd. Vaga fel leder till förvirrade agenter.
Dåligt fel:
{ "error": "Ogiltiga indata" }
Bättre fel:
{
"error": "validation_error",
"message": "E-postadressen '...' har inte ett giltigt format. Den måste se ut som 'name@example.com'.",
"field": "email",
"suggestion": "Be användaren om en giltig e-postadress."
}
LLM-modellen vet nu:
- Vad som gick fel (valideringsfel i e-postfältet).
- Hur felet åtgärdas (använd ett giltigt format för e-postadressen).
- Vad den ska göra härnäst (fråga användaren).
Jämför en agents beteende med de två felen. Det första kan leda till att agenten försöker med samma anrop igen (slöseri), ger upp (dålig UX) eller hittar på giltiga indata. Det andra leder till en smidig användarinteraktion.
Princip 5: Utdata formar nästa åtgärd
Verktygets utdata avgör vad LLM-modellen gör härnäst. Utformningen av utdata påverkar agentens beteende.
Dåliga utdata för en sökning:
[
{"id": "c1", "n": "John", "e": "john@..."},
{"id": "c2", "n": "Jane", "e": "jane@..."}
]
Bättre utdata:
{
"customers": [
{"id": "c1", "name": "John Smith", "email": "john@example.com", "tier": "pro"},
{"id": "c2", "name": "Jane Doe", "email": "jane@example.com", "tier": "free"}
],
"total_found": 2,
"summary": "Hittade 2 kunder som matchar 'john'. Observera att den ena heter 'Jane Doe' men har 'john' i sin e-postadress."
}
De bättre utdata:
- Använder läsbara fältnamn.
- Innehåller metakontext (
total_found). - Innehåller en
summarypå naturligt språk som hjälper LLM-modellen att formulera vad den ska säga härnäst.
Sammanfattningsfältet är kraftfullt – det är som att ge LLM-modellen en liten upplysning i förbifarten om hur resultatet ska tolkas.
Princip 6: Ett verktyg, en sak
Verktyg som gör flera saker förvirrar LLM-modeller. LLM-modellen måste avgöra både om verktyget ska användas OCH vilket läge som ska användas.
Förvirrande:
manage_customer:
- mode: "search" | "get" | "update" | "delete"
- params: beror på mode
LLM-modellen måste välja läge. Den väljer ofta fel. Än värre: parameterschemat blir komplicerat eftersom det varierar beroende på läge.
Bättre: separata verktyg.
search_customers: sök efter namn/e-postadress/företag
get_customer: hämta uppgifter efter ID
update_customer: uppdatera specifika fält
delete_customer: arkivera en kund
Varje verktyg är entydigt. LLM-modellen väljer ett utifrån avsikten. Schemana är enkla.
Det innebär fler verktyg, men vart och ett är tydligare. LLM-modellen hanterar 10 tydliga verktyg bättre än 3 verktyg med flera lägen.
Princip 7: Begränsa indata
Begränsa alternativen för indata där det är möjligt. Enum-värden och validering förhindrar att LLM-modellen hittar på värden.
Obegränsat:
{
status: string // kan vara vad som helst
}
Begränsat:
{
status: "active" | "trial" | "churned" | "suspended"
}
Begränsningen tillämpas på schemanivå (begränsad generering hindrar LLM-modellen från att skapa ogiltiga värden).
Detsamma gäller enum-värden för åtgärder, allvarlighetsgrader och typer – allt med en känd uppsättning giltiga värden.
Använd ISO 8601-format för datum och ange det i beskrivningen (”Datum i ISO 8601-format, till exempel 2026-05-15”). Utan detta skapar LLM-modeller datum i godtyckliga format.
Princip 8: Standardvärden minskar risken för påhittade värden
När parametrar har rimliga standardvärden bör du göra dem valfria och tillämpa standardvärdet på serversidan.
Dåligt:
{
query: string,
limit: number, // LLM-modellen måste ange ett värde
include_archived: boolean,
sort_by: string
}
LLM-modellen måste välja värden för alla dessa. De kan bli fel.
Bättre:
{
query: string,
limit: number = 10, // rimligt standardvärde
include_archived: boolean = false, // säkert standardvärde
sort_by: "relevance" | "name" | "created_at" = "relevance" // vanligast
}
LLM-modellen anger bara parametrar som är relevanta för den specifika frågan. Färre parametrar innebär mindre utrymme för förvirring.
Dokumentera standardvärden i beskrivningen: ”Limit: antal resultat som ska returneras. Standardvärde 10, högst 50.”
Princip 9: Möjligheten att kombinera verktyg spelar roll
Verktyg bör kunna kombineras till arbetsflöden som LLM-modellen kan konstruera. Rätt granularitet gör komplexa uppgifter enkla.
Tänk dig uppgiften: ”Berätta om alla öppna ärenden för våra 3 främsta kunder.”
Dålig verktygsuppsättning:
get_customer_summary(customer_id): returnerar kund + supportärenden + aktivitet i ett enda svar
LLM-modellen kan inte enkelt använda filtret för ”3 främsta” – verktyget returnerar allt för en kund i taget. För att utföra uppgiften måste LLM-modellen först veta vilka de främsta kunderna är och sedan anropa verktyget 3 gånger.
Bättre verktygsuppsättning:
list_customers(sort_by="value", limit=N): returnerar kundsammanfattningar med prioritetsinformation
list_tickets(customer_id, status): returnerar supportärenden för en kund
LLM-modellen kan kombinera verktygen: lista de främsta kunderna och lista sedan öppna supportärenden för var och en. Sammansättningen är naturlig.
Principen är att tänka på arbetsflöden med flera verktyg. Verktyg som fungerar väl ihop är användbara; verktyg som inte gör det är ofta oanvändbara.
Princip 10: Idempotens kommuniceras
För skrivverktyg ska kraven på idempotens anges i beskrivningen:
create_invoice: Skapa en ny faktura för en kund.
VIKTIGT: Skicka med en idempotency_key (ett UUID som du genererar). Om du försöker utföra åtgärden igen ska du använda samma UUID för att förhindra dubblettfakturor.
Parametrar:
- amount: ...
- customer_id: ...
- idempotency_key: UUID för att förhindra dubbletter vid nya försök. Generera en gång per logisk åtgärd.
Nu vet LLM-modellen att den ska generera ett UUID och använda samma värde vid ett nytt försök.
Utan denna vägledning kan LLM-modellen antingen utelämna nyckeln (ingen idempotens) eller generera ett nytt UUID vid varje nytt försök (vilket motverkar syftet).
Princip 11: Ange för- och eftervillkor
För verktyg med förvillkor eller viktiga sidoeffekter ska detta anges:
delete_customer: Arkivera en kundpost. Detta kan ångras inom 30 dagar. Efter 30 dagar raderas data permanent.
FÖRVILLKOR:
- Kunden får inte ha några aktiva abonnemang.
- Kunden får inte ha några öppna supportärenden.
Om förvillkoren inte är uppfyllda returnerar verktyget ett fel som anger vad som först måste åtgärdas.
SIDOEFFEKTER:
- Alla kundens kontakter arkiveras också.
- Kunden tas bort från aktiva rapporter.
- En post skapas i revisionsloggen.
LLM-modellen vet nu vad den ska kontrollera före anropet och vad den kan förvänta sig efteråt. Den kan planera arbetsflöden i flera steg korrekt (”stäng först kundens supportärenden och radera sedan kunden”).
Princip 12: Använd exempel när du är osäker
För komplexa verktyg hjälper det att ta med ett exempel i beskrivningen:
analyze_funnel: Analysera en konverteringstratt utifrån händelsedata.
Parametrar:
- start_date: ISO 8601-datum
- end_date: ISO 8601-datum
- steps: array med stegdefinitioner, var och en {event_name: string, filters?: object}
Exempel:
{
"start_date": "2026-01-01",
"end_date": "2026-01-31",
"steps": [
{"event_name": "signup"},
{"event_name": "first_login"},
{"event_name": "first_action", "filters": {"action_type": "create_project"}},
{"event_name": "subscription_started"}
]
}
Exempel lär LLM-modellen strukturen bättre än enbart scheman.
Princip 13: Exponera inte interna detaljer
LLM-modellen behöver inte känna till din databasstruktur eller interna ID:n. Visa en ren begreppsmodell.
Dåligt:
get_user_by_pk(pk: number)
LLM-modellen måste veta att den ska använda ”primärnyckeln” – ett databasbegrepp.
Bättre:
get_user(user_id: string)
Dölj databasbegreppet. LLM-modellen använder ett user_id, vilket är ett meningsfullt begrepp.
Exponera på samma sätt inte utfasade fält, interna flaggor, felsökningsparametrar eller något annat som rör din implementation i stället för det användarnära begreppet.
Princip 14: Undvik magiska strängar
Vissa verktyg kräver strängar som ser ut som kommandon eller koder. De är felbenägna.
Dåligt:
modify_record(record_id: string, change_string: string)
// där change_string ser ut så här: "field1=value1;field2=value2"
LLM-modellen måste koda ändringarna i ett specifikt strängformat. Den kommer att göra fel.
Bättre:
update_record(record_id: string, updates: { field1?: any; field2?: any; ... })
Strukturerade uppdateringar som ett objekt. LLM-modellen kan använda valfritt fält direkt.
Princip 15: Testa med riktiga LLM-modeller
Verktygsbeskrivningar kan vara tydliga för människor men förvirrande för LLM-modeller. Det enda sättet att veta är att testa.
Ett användbart arbetsflöde:
- Bygg verktyget.
- Låt en LLM-agent försöka utföra flera realistiska uppgifter enbart med dina verktyg.
- Observera felen.
- Justera beskrivningarna utifrån felen.
- Upprepa.
Du kommer att se följande mönster:
- LLM-modellen använder fel verktyg → verktygets namn eller beskrivning är otydlig.
- LLM-modellen skickar fel parametervärden → parameterbeskrivningen eller schemat behöver förbättras.
- LLM-modellen ger upp efter fel → felmeddelandena behöver förbättras.
- LLM-modellen försöker inte använda ett verktyg som skulle hjälpa → verktyget exponeras inte tillräckligt tydligt eller har ett otydligt namn.
Varje problem pekar på en specifik lösning.
Diagnos: tecken på att dina verktyg inte är väl utformade
Några mönster som tyder på problem med verktygsdesignen:
LLM-modellen använder ofta fel verktyg. Du ser den anropa search_customers när den borde ha anropat get_customer_by_id. Lösning: förtydliga vilket verktyg som ska användas i vilken situation.
LLM-modellen anropar många verktyg för att göra en sak. Den kedjar ihop 5 verktygsanrop för att utföra något som borde kräva 1. Lösning: du kanske behöver ett sammansatt verktyg på högre nivå eller så är granulariteten för fin.
LLM-modellen ger upp efter fel. Den försöker en gång, får ett fel och säger sedan till användaren att den inte kan hjälpa till. Lösning: bättre felmeddelanden som föreslår nästa steg.
LLM-modellen hittar på parametervärden. Den hittar på user_ids, datum och ID:n. Lösning: förtydliga hur giltiga värden hämtas, lägg till begränsningar och lägg till felhantering som fångar och förklarar problemet.
LLM-modellen upprepar samma misslyckade anrop. Samma fel upprepas. Lösning: felmeddelandet talar inte tillräckligt specifikt om vad som är fel.
LLM-modellen använder inte ett kraftfullt verktyg. Du har byggt ett utmärkt verktyg, men LLM-modellen anropar det aldrig. Lösning: förbättra möjligheten att hitta det (tydligare namn, bättre beskrivning och vägledning i stil med ”använd detta när …”).
Verktygstaxonomi
En användbar övning är att ordna verktygen i en taxonomi.
Läsverktyg (säkra, idempotenta):
- search_customers
- get_customer_by_id
- list_tickets
- list_orders
Beräkningsverktyg (inga tillståndsändringar):
- summarize_account_activity
- analyze_funnel
- calculate_lifetime_value
Skrivverktyg (tillståndsändringar, kräver idempotens):
- create_customer
- update_customer_email
- create_ticket
- send_email
Destruktiva verktyg (kräver noggrann behörighetskontroll):
- delete_customer
- cancel_subscription
- archive_record
Taxonomin hjälper dig att:
- Tillämpa lämpliga skyddsräcken (idempotens och bekräftelse för destruktiva åtgärder).
- Dokumentera kategorierna för LLM-modellen i systemprompter.
- Upptäcka verktyg som saknas (behöver du ett om en kategori är tom?).
Ett användbart tillägg till systemprompten:
Tillgängliga verktygskategorier:
- READ-verktyg (säkra att anropa): search_customers, get_customer_by_id, ...
- COMPUTE-verktyg (inga sidoeffekter): summarize_account_activity, ...
- WRITE-verktyg (sidoeffekter, inkludera idempotency_key): create_customer, ...
- DESTRUCTIVE-verktyg (kräver mänsklig bekräftelse): delete_customer, ...
Bekräfta med användaren innan du anropar ett WRITE- eller DESTRUCTIVE-verktyg.
Detta formar hur LLM-modellen använder verktygen på arbetsflödesnivå, inte bara för varje enskilt anrop.
Exempel på vanliga förbättringar
För att konkretisera principerna följer här exempel före och efter:
Exempel 1: Ett sökverktyg
Före:
// sök dokument
{
name: "documents",
description: "Sök dokument",
inputSchema: { query: "string" }
}
Efter:
{
name: "search_documents",
description: `Sök i interna dokument (kunskapsbas, wikisidor, policyer).
Returnerar matchande dokument med titel, utdrag och länk. Använd när användaren frågar om företagets policyer, rutiner eller interna dokumentation. Returnerar upp till 10 mest relevanta träffar efter semantisk likhet.`,
inputSchema: {
query: {
type: "string",
description: "Sökfråga. Var specifik. Bra: 'policy för distansarbete 2026'. Dåligt: 'dokument om arbete'."
},
document_type: {
type: "string",
enum: ["policy", "procedure", "guide", "faq", "any"],
default: "any",
description: "Filtrera på en viss dokumenttyp."
},
limit: {
type: "number",
default: 5,
maximum: 10,
description: "Antal resultat."
}
}
}
Exempel 2: Ett åtgärdsverktyg
Före:
{
name: "send_email",
description: "Skicka ett e-postmeddelande",
inputSchema: {
to: "string",
subject: "string",
body: "string"
}
}
Efter:
{
name: "draft_email_to_customer",
description: `Skriv ett utkast till ett e-postmeddelande till en kund utifrån en nylig interaktion. Meddelandet sparas som ett utkast för mänsklig granskning innan det skickas – det skickas INTE automatiskt. Användaren måste godkänna utkast i sin inkorg.
Använd när:
- Du har identifierat en åtgärd som kräver uppföljning med kunden.
- Du har ett specifikt skäl och innehåll för e-postmeddelandet.
Använd INTE:
- För att skicka marknadsförings- eller reklaminnehåll.
- Utan en uttrycklig begäran från användaren.
- För att besvara begäranden om återbetalning eller uppsägning (eskalera i stället till en människa).`,
inputSchema: {
customer_id: {
type: "string",
description: "Kund-ID från search_customers eller get_customer."
},
subject: {
type: "string",
description: "Ämnesrad, 4–8 ord, specifik. Undvik generiska ämnesrader som 'Uppföljning'."
},
body: {
type: "string",
description: "Meddelandetext, vanlig text. 3–5 meningar. Personlig, specifik, inte mallartad."
},
tone: {
type: "string",
enum: ["professional", "friendly", "apologetic", "urgent"],
default: "professional",
description: "E-postmeddelandets ton."
},
idempotency_key: {
type: "string",
description: "UUID för detta utkast. Använd samma UUID vid ett nytt försök för att undvika dubbletter."
}
}
}
Versionerna ”Efter” vägleder LLM-modellen betydligt effektivare. De kan kännas omständliga, men de är värda det.
Slutsats
Verktygsdesign för LLM-modeller är en egen disciplin. Principerna är inte intuitiva; de kräver att du betraktar LLM-modellen som din användare och utformar gränssnittet därefter.
Mönstren som spelar roll:
- Namn med handlingsverb.
- Utförliga beskrivningar som förklarar vad, när och när inte.
- Beskrivningar per parameter med exempel och begränsningar.
- Strukturerade, användbara felmeddelanden.
- Utdataformat som vägleder nästa åtgärd.
- Ett verktyg per begrepp.
- Rimliga standardvärden.
- Granularitet som gör verktygen kombinerbara.
- Uttrycklig idempotens.
- Dokumenterade för- och eftervillkor.
- Exempel för komplexa verktyg.
- Dolda interna detaljer.
- Testning med riktiga LLM-modeller.
De flesta MCP-servrar misslyckas inte för att protokollet är svårt, utan för att verktygen inte utformades med LLM-modellen i åtanke. Rätt verktygsdesign gör servern effektiv; fel verktygsdesign gör att din avancerade backend går till spillo.
Behandla LLM-modellen som användaren. Utforma därefter. Investeringen betalar sig många gånger om genom att verktygen faktiskt används mycket bättre.



