← Terug naar blog

Odoo 19.4 heeft een eigen MCP-server. Wat zit erin, en wie krijgt hem?

Odoo 19.4 heeft een eigen MCP-server op /mcp, zonder module om te installeren. Er zitten vijf tools in en alle vijf kunnen alleen lezen. We hebben saas-19.4 lokaal gedraaid en het de server zelf gevraagd: dit is de lijst, dit zijn de twee nieuwe vinkjes die bepalen wat erin komt, zo werkt het samen met je toegangsrechten, en dit is waarom de meeste Odoo-databases hem voorlopig niet krijgen.

Odoo heeft nu een eigen MCP-server. Je wijst je AI-tool naar /mcp, logt in met een API-sleutel, en het werkt zonder dat je een module uit de App Store installeert. De meeste stukken hierover noemen het een functie van Odoo 20 en zijn geschreven op basis van aankondigingen. Hij is er eerder, hij kan minder dan de aankondigingen suggereren, en de meeste Odoo-databases krijgen hem voorlopig niet.

Vijf tools, en alle vijf kunnen alleen lezen.

We hebben dat gecontroleerd door Odoo saas-19.4 lokaal te draaien en het de server zelf te vragen. Alles hieronder komt van die instance, en je kunt het allemaal nadoen op die van jou.

Vraag het de server zelf

Begin hier, want de rest van dit stuk is alleen wat waard als je het kunt narekenen.

Je hebt een API-sleutel nodig met de MCP-scope. Log in, klik op je avatar, ga naar het tabblad beveiliging en maak een sleutel aan. Het verschil met een gewone sleutel zit in het keuzemenu bij scope: kies MCP in plaats van de standaardwaarde. Stuur daarna een JSON-RPC-verzoek naar het endpoint, met je sleutel als bearer token in de authorization-header, en vraag om de methode tools/list.

Dit komt eruit, met de schema's en omschrijvingen ingekort:

{
  "result": {
    "tools": [
      { "name": "ai_tool_get_fields",
        "annotations": { "readOnlyHint": true, "destructiveHint": false } },
      { "name": "ai_tool_get_models",
        "annotations": { "readOnlyHint": true, "destructiveHint": false } },
      { "name": "ai_tool_mcp_retrieve_initial_context",
        "annotations": { "readOnlyHint": true, "destructiveHint": false } },
      { "name": "ai_tool_read_group",
        "annotations": { "readOnlyHint": true, "destructiveHint": false } },
      { "name": "ai_tool_search",
        "annotations": { "readOnlyHint": true, "destructiveHint": false } }
    ]
  }
}

Vijf tools. Bij alle vijf staat readOnlyHint: true.

Wat je krijgt

ai_tool_mcp_retrieve_initial_context geeft terug wie je bent, in welke tijdzone je zit, welk bedrijf actief is en welke bedrijven je mag zien. Odoo draagt de AI-tool op om die als eerste aan te roepen, voor al het andere, omdat de rest anders verkeerde antwoorden geeft. Vraag om "dit kwartaal" in de verkeerde tijdzone en je krijgt het verkeerde kwartaal.

De andere vier doen het werk. ai_tool_get_models geeft de modellen die je mag zien, ai_tool_get_fields geeft de velden waarop je kunt zoeken, ai_tool_search zoekt records op en ai_tool_read_group groepeert en telt op.

Die combinatie is goed in één ding: vragen beantwoorden over je eigen gegevens. "Hoeveel openstaande offertes boven 10k hebben we dit kwartaal verstuurd, per verkoper?" werkt, en werkt goed. Als dat is wat je van AI in je ERP wilde, dan doet de server van Odoo dat, kost het niets extra en ben je in vijf minuten klaar. Een hoop mensen willen precies dat en kunnen hier stoppen met lezen.

Wat er niet in zit

Vraag het endpoint om iets aan te maken en je krijgt geen weigering. Je krijgt te horen dat de tool niet bestaat:

{ "result": { "content": [ { "type": "text",
  "text": "The tool ai_tool_create_records does not exist" } ],
  "isError": true } }

Niets aanmaken, niets wijzigen, niets verwijderen, geen methodes aanroepen. Niets dat schrijft.

Dat is een keuze, geen omissie. De tool bestaat, staat geregistreerd en draait. Hij wordt alleen niet aan jou getoond.

Hoe groot die keuze is zie je in de database. De AI-tools van Odoo zijn server actions, en elke tool heeft twee losse schakelaars: een voor de eigen chat van Odoo, een voor MCP. Op een schone 19.4 staan er twintig aan voor de chat. Vijf staan er aan voor MCP. Bij de zestien die de chat wel krijgt en jij niet zitten ai_tool_create_records, ai_tool_update_records, ai_tool_run_view_action en ai_tool_web_search.

Zelfde database, zelfde rechten, ander antwoord afhankelijk van welke kant het verzoek vandaan komt. De assistent van Odoo schrijft. Die van jou leest.

De twee nieuwe velden

Zet de ontwikkelaarsmodus aan en ga naar Instellingen, dan Technisch, dan Server Actions. De AI-tools staan daar als records, op het model ir.actions.server, en twee vinkjes bepalen hoe elke tool zich via MCP gedraagt.

"Available in MCP" bepaalt of de tool überhaupt in tools/list verschijnt.

"Readonly Tool" is wat de server als readOnlyHint doorgeeft aan je AI-tool.

Het zijn allebei instellingen op een record, en dat heeft gevolgen die je wilt kennen voordat je op een van beide vertrouwt.

De grens tussen lezen en schrijven is een vinkje

We hebben "Available in MCP" aangezet op ai_tool_create_records op onze testinstance. Eén veld op één record. De volgende tools/list gaf zes tools in plaats van vijf, met de nieuwe eerlijk gelabeld:

{ "name": "ai_tool_create_records",
  "annotations": { "readOnlyHint": false, "destructiveHint": true } }

Die lijst van vijf is dus een standaardinstelling, geen muur. Als jij een Odoo beheert, dan is jouw MCP net zo alleen-lezen als je server actions zijn ingesteld. Ga dus kijken in plaats van aannemen.

Het betekent ook dat schrijven vanuit een externe AI-tool via de MCP van Odoo een ondersteunde route is, geen achterdeur. Je bent alleen zelf degene die het besluit, en die het resultaat draagt.

De twee velden controleren elkaar niet

"Readonly Tool" is een handmatig vinkje. Niets dwingt af dat het klopt met wat de tool doet.

We lieten ai_tool_create_records aan staan en zetten er ook "Readonly Tool" bij aan. De server meldde dit vervolgens aan de AI-tool:

{ "name": "ai_tool_create_records",
  "annotations": { "readOnlyHint": true, "destructiveHint": false } }

Daarna riepen we hem aan, en hij maakte een contact aan. Id 7, netjes in res_partner, aangemaakt door een tool die tegen onze AI zei dat hij alleen leest.

Die aanduiding is een mededeling aan de AI-tool, geen slot in de server. Niets controleert het. Zet je dat vinkje verkeerd, dan gelooft je AI-tool het, en een tool die op readOnlyHint afgaat om te bepalen wanneer hij jou om bevestiging vraagt, slaat die vraag over.

Wat Odoo meelevert klopt met elkaar, dus dit is een val die je zelf moet bouwen. Goed om te weten dat hij er is voordat je zelf gaat sleutelen.

Hoe dit samenwerkt met je toegangsrechten

Het geruststellende deel: de MCP verzint geen nieuw rechtenmodel.

We schreven eerder een gids over hoe toegangsrechten in Odoo echt werken. Kort gezegd passeert elke actie vier poorten: je groepen, dan ir.model.access op modelniveau, dan record rules die bepalen welke regels je ziet, dan de rechten per veld. Eén "nee" stopt de actie.

Een MCP-verzoek gaat door alle vier, ongewijzigd. De reden staat in die gids: een API-sleutel geeft uit zichzelf geen enkel recht, hij zegt alleen "ik ben deze gebruiker". Een sleutel met de MCP-scope blijft gewoon jou.

We hebben dat getest met twee sleutels op dezelfde instance, een van een beheerder en een van een gewone gebruiker. Allebei kregen ze dezelfde vijf tools terug uit tools/list. De lijst verschilt dus niet per gebruiker.

Wat er doorheen komt verschilt wel. ai_tool_get_models gaf de beheerder 88 modellen. Dezelfde aanroep met de sleutel van de gewone gebruiker gaf er 56, en die 56 waren een strikte deelverzameling: geen enkel model dook op bij de gewone gebruiker dat de beheerder niet kon zien. De AI heeft jouw rechten, en de vier poorten filteren precies zoals ze dat in het scherm doen.

De keerzijde is dat er geen knop is om het lager te zetten. Je kunt niet zeggen: deze persoon mag in het scherm alles, maar via AI alleen klanten lezen. De sleutel is de gebruiker. Wil je de AI minder geven, dan maak je een tweede Odoo-gebruiker met minder rechten en geef je die de sleutel, en dat is gewoon een gebruiker op je factuur. Slaat iemand die stap over, dan pakt hij zijn eigen beheerdersaccount, en heeft de assistent beheerdersrechten op alles. Dat de lijst vandaag alleen leest is een geruststelling met een houdbaarheidsdatum, namelijk zolang de standaardinstellingen staan.

Nog een detail dat opvalt als je er toch bent. Toen we voor de gewone gebruiker een sleutel zonder vervaldatum wilden maken, weigerde Odoo dat: "The API key must have an expiration date." Voor de beheerder gold die eis niet. Sleutels van gewone gebruikers verlopen, die van beheerders kunnen eeuwig leven, en dat wijst de verkeerde kant op als gemak je keuze bepaalt.

Wie krijgt dit, en wanneer?

Dit bepaalt of het bovenstaande jou al iets aangaat, en de versienummers zetten je hier flink op het verkeerde been.

Odoo Online en al het andere zitten op verschillende sporen. Odoo Online rijdt mee op de SaaS-releases: 19.1, dan 19.2, dan 19.3, dan 19.4. Odoo zet die databases zelf door, een paar keer per jaar, en jij hebt daar geen stem in. Odoo.sh en eigen servers draaien de hoofdversies: 18.0, dan 19.0, dan 20.0.

En in 19.0 zit de MCP-module niet. Geen oudere versie ervan. Hij is er niet. We hebben elke branch nagekeken: de module bestaat in saas-19.4 en in de ontwikkelbranch van Odoo, en in geen enkele andere, 19.0 inbegrepen.

saas-19.4 is dus niet "nieuwer dan 19.0" zoals de nummers doen vermoeden. Het zijn parallelle sporen. Een Odoo.sh-klant op 19.0 wordt nooit 19.4. Die gaat naar 20.0.

Dat geeft drie behoorlijk verschillende antwoorden:

  • Odoo Online. Je hebt het, of je krijgt het binnen een paar maanden, zonder iets te doen.
  • Odoo.sh en eigen server met Enterprise. Niets tot de volgende hoofdversie. De module zit in de ontwikkelbranch, dus 20.0 zal hem waarschijnlijk hebben, maar in 19.0 komt hij niet meer.
  • Community. Nooit. Hij zit in de enterprise-repository van Odoo onder een gesloten licentie, en hij hangt aan de betaalde AI-module.

Die middelste regel wordt vaak weggewuifd. Van 18.0 of 19.0 naar 20.0 is een project: eigen modules, testen, een periode waarin dingen stuk zijn, een budget en een datum. Ben je partner met dertig klanten, dan leest "we krijgen MCP bij 20" als "we krijgen MCP na dertig upgradeprojecten". De meeste van die databases zijn een jaar of langer verwijderd van een endpoint dat toch alleen leest.

Waar wij passen

Wij maken Odoo MCP Pro, en de verschillen volgen uit de drie dingen waar dit stuk steeds omheen cirkelt.

Hij schrijft, en verder dan aanmaken en wijzigen. Er zit een tool in die execute_method heet en die elke methode op elk model kan aanroepen, zodat een assistent een wizard kan draaien, een betaling kan boeken of een banklijn kan afletteren in plaats van erover te vertellen. Het is ook de tool die de meeste zorg verdient, en daarom bestaat het punt hierna.

Hij houdt meer dan één Odoo vast. Eén koppeling voor alle klantinstances, en je wisselt ertussen midden in een gesprek. Het endpoint van Odoo is per definitie één database, en dat is geen vergissing die ze even repareren: ze verkopen per database.

Hij kan lager dan de gebruiker. Onze governance-module geeft een sleutel een eigen rol en logt elke aanroep, zodat de assistent minder mag dan de persoon die de sleutel heeft. Dat is precies de knop die het model van Odoo niet heeft.

En hij draait op 14 tot en met 19, Community inbegrepen, op elke vorm van hosting. Gezien de sporen hierboven is dat het grootste deel van alle Odoo die er vandaag staat.

Tot slot, eerlijk is eerlijk

Alles hierboven beschrijft een standaardinstelling, en die kunnen veranderen. Odoo heeft de schrijf-tools al gebouwd en ze draaien al in hun eigen assistent. Wij zetten er van buitenaf een aan met één veld, en dat zegt genoeg over hoe ver het alternatief weg is: het openzetten is een instelling, geen bouwproject. Als het commercieel uitkomt voor Odoo kan het in een tussenrelease landen.

De vorm van het geheel verandert minder makkelijk. Eén database per endpoint, één editie, één releasespoor. Dat is een keuze over een verdienmodel en niet over een vinkje, en daar zit het verschil dat de moeite van het volgen waard is.