@maideo/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +97 -0
- package/package.json +43 -0
- package/src/index.js +360 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maideo Services
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @maideo/mcp
|
|
2
|
+
|
|
3
|
+
Official MCP (Model Context Protocol) server for the Maideo Agent API.
|
|
4
|
+
|
|
5
|
+
Lets any MCP-compatible AI agent (Claude Desktop, Claude Code, ChatGPT desktop, Continue.dev, Cursor, etc.) book professional home cleaning services (ménage à domicile) anywhere in France, end-to-end, without human intervention.
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
- Checks coverage by postal code
|
|
10
|
+
- Returns a firm price quote
|
|
11
|
+
- Creates a booking in Maideo's back-office (visible to the ops team)
|
|
12
|
+
- Enrolls the end user with URSSAF for the 50% immediate tax credit advance (no card payment needed — SEPA direct debit after each intervention)
|
|
13
|
+
- Polls booking status
|
|
14
|
+
|
|
15
|
+
## Tools exposed
|
|
16
|
+
|
|
17
|
+
| Tool | Purpose |
|
|
18
|
+
|------|---------|
|
|
19
|
+
| `search_coverage` | Check if Maideo serves a zip code |
|
|
20
|
+
| `get_quote` | Get a firm 72h-valid price quote |
|
|
21
|
+
| `create_booking` | Create the booking (returns a 72h `bookingToken`) |
|
|
22
|
+
| `enroll_avance_immediate` | Submit URSSAF enrollment (IBAN + identity) |
|
|
23
|
+
| `get_booking_status` | Poll status (order, worker, URSSAF) |
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install -g @maideo/mcp
|
|
29
|
+
# or use npx without installing:
|
|
30
|
+
npx @maideo/mcp
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configure Claude Desktop
|
|
34
|
+
|
|
35
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"maideo": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@maideo/mcp"],
|
|
43
|
+
"env": {
|
|
44
|
+
"MAIDEO_AGENT_NAME": "claude-desktop"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Restart Claude Desktop. You can now ask Claude:
|
|
52
|
+
|
|
53
|
+
> "Can you book me a weekly 3-hour cleaning at 12 rue de Rivoli, 75001 Paris, starting next Monday?"
|
|
54
|
+
|
|
55
|
+
Claude will chain the 5 tools automatically.
|
|
56
|
+
|
|
57
|
+
## Configure Claude Code
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
claude mcp add maideo npx -- -y @maideo/mcp
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Environment variables
|
|
64
|
+
|
|
65
|
+
| Variable | Default | Purpose |
|
|
66
|
+
|----------|---------|---------|
|
|
67
|
+
| `MAIDEO_API_BASE` | `https://api.maideo.fr/public/agent` | API base URL (override for staging/dev) |
|
|
68
|
+
| `MAIDEO_AGENT_NAME` | `maideo-mcp-client` | Identifier sent via `X-Agent-Name` header (used for rate limiting and analytics) |
|
|
69
|
+
|
|
70
|
+
## Anti-fraud hold
|
|
71
|
+
|
|
72
|
+
All bookings created via this MCP server are held for 48h before worker dispatch. The Maideo ops team may phone/SMS the end user to verify. **Do not submit bookings with fake data in production.** Your `MAIDEO_AGENT_NAME` may be blocklisted.
|
|
73
|
+
|
|
74
|
+
You must also collect explicit consent from the end user before calling `create_booking`. Pass `agentConsent: true` as a binding attestation.
|
|
75
|
+
|
|
76
|
+
## How payment works (there is no payment step)
|
|
77
|
+
|
|
78
|
+
Maideo uses the URSSAF **avance immédiate de crédit d'impôt** (immediate tax credit advance), a French government program for home services.
|
|
79
|
+
|
|
80
|
+
1. End user enrolls via `enroll_avance_immediate` — provides identity, birth place, address, IBAN
|
|
81
|
+
2. Worker does the cleaning
|
|
82
|
+
3. Maideo declares the hours to URSSAF
|
|
83
|
+
4. URSSAF pays Maideo directly for 50% of the amount (the tax credit portion)
|
|
84
|
+
5. URSSAF collects the remaining 50% from the end user via SEPA direct debit
|
|
85
|
+
|
|
86
|
+
**No card, no Stripe, no upfront payment, no signed PDF.** The IBAN + identity are enough.
|
|
87
|
+
|
|
88
|
+
## Links
|
|
89
|
+
|
|
90
|
+
- [Maideo website](https://www.maideo.fr)
|
|
91
|
+
- [OpenAPI spec](https://www.maideo.fr/openapi.json)
|
|
92
|
+
- [Agents policy](https://www.maideo.fr/agents.txt)
|
|
93
|
+
- [LLMs manifest](https://www.maideo.fr/llms.txt)
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maideo/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official MCP server for the Maideo Agent API — book home cleaning services in France end-to-end",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"maideo-mcp": "src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src/",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"start": "node src/index.js",
|
|
17
|
+
"dev": "MAIDEO_API_BASE=http://localhost:3000/public/agent node src/index.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"model-context-protocol",
|
|
22
|
+
"maideo",
|
|
23
|
+
"cleaning",
|
|
24
|
+
"menage",
|
|
25
|
+
"france",
|
|
26
|
+
"claude",
|
|
27
|
+
"chatgpt",
|
|
28
|
+
"agent"
|
|
29
|
+
],
|
|
30
|
+
"author": "Maideo <dev@maideo.fr>",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=20"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/maideo/maideo-mcp"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://www.maideo.fr/agents.txt"
|
|
43
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @maideo/mcp — Official MCP server for the Maideo Agent API.
|
|
4
|
+
*
|
|
5
|
+
* Exposes 5 tools that map 1:1 on the public HTTP API:
|
|
6
|
+
* - search_coverage
|
|
7
|
+
* - get_quote
|
|
8
|
+
* - create_booking
|
|
9
|
+
* - enroll_avance_immediate
|
|
10
|
+
* - get_booking_status
|
|
11
|
+
*
|
|
12
|
+
* Runs over stdio. Install with `npm i -g @maideo/mcp` then add to your
|
|
13
|
+
* Claude Desktop / Claude Code / ChatGPT MCP client config.
|
|
14
|
+
*/
|
|
15
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
16
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
|
+
import {
|
|
18
|
+
CallToolRequestSchema,
|
|
19
|
+
ListToolsRequestSchema,
|
|
20
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
|
|
22
|
+
const API_BASE =
|
|
23
|
+
process.env.MAIDEO_API_BASE || "https://api.maideo.fr/public/agent";
|
|
24
|
+
const AGENT_NAME =
|
|
25
|
+
process.env.MAIDEO_AGENT_NAME || "maideo-mcp-client";
|
|
26
|
+
|
|
27
|
+
async function apiRequest(path, { method = "GET", body, bookingToken } = {}) {
|
|
28
|
+
const headers = {
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
"X-Agent-Name": AGENT_NAME,
|
|
31
|
+
};
|
|
32
|
+
if (bookingToken) {
|
|
33
|
+
headers["Authorization"] = `Bearer ${bookingToken}`;
|
|
34
|
+
}
|
|
35
|
+
const res = await fetch(`${API_BASE}${path}`, {
|
|
36
|
+
method,
|
|
37
|
+
headers,
|
|
38
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
39
|
+
});
|
|
40
|
+
const text = await res.text();
|
|
41
|
+
let data;
|
|
42
|
+
try {
|
|
43
|
+
data = text ? JSON.parse(text) : {};
|
|
44
|
+
} catch {
|
|
45
|
+
data = { raw: text };
|
|
46
|
+
}
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
const err = new Error(
|
|
49
|
+
`Maideo API ${res.status}: ${data.error || res.statusText}`
|
|
50
|
+
);
|
|
51
|
+
err.statusCode = res.status;
|
|
52
|
+
err.details = data.details;
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
return data;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const server = new Server(
|
|
59
|
+
{
|
|
60
|
+
name: "@maideo/mcp",
|
|
61
|
+
version: "0.1.0",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
capabilities: {
|
|
65
|
+
tools: {},
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const TOOLS = [
|
|
71
|
+
{
|
|
72
|
+
name: "search_coverage",
|
|
73
|
+
description:
|
|
74
|
+
"Check whether Maideo serves a given French postal code and get the estimated hourly rate (gross, before the 50% tax credit advance). Use this BEFORE get_quote.",
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: "object",
|
|
77
|
+
required: ["zip"],
|
|
78
|
+
properties: {
|
|
79
|
+
zip: {
|
|
80
|
+
type: "string",
|
|
81
|
+
pattern: "^[0-9]{5}$",
|
|
82
|
+
description: "5-digit French postal code",
|
|
83
|
+
},
|
|
84
|
+
prestation: {
|
|
85
|
+
type: "string",
|
|
86
|
+
enum: ["MENAGE"],
|
|
87
|
+
default: "MENAGE",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "get_quote",
|
|
94
|
+
description:
|
|
95
|
+
"Get a firm price quote for a cleaning booking. Returns a quoteToken valid for 72h that must be passed to create_booking.",
|
|
96
|
+
inputSchema: {
|
|
97
|
+
type: "object",
|
|
98
|
+
required: ["zip", "nbHeuresSemaine", "frequency"],
|
|
99
|
+
properties: {
|
|
100
|
+
zip: { type: "string", pattern: "^[0-9]{5}$" },
|
|
101
|
+
city: { type: "string" },
|
|
102
|
+
nbHeuresSemaine: {
|
|
103
|
+
type: "number",
|
|
104
|
+
minimum: 2,
|
|
105
|
+
description: "Number of hours per intervention",
|
|
106
|
+
},
|
|
107
|
+
nbPrestaSemaine: {
|
|
108
|
+
type: "integer",
|
|
109
|
+
default: 1,
|
|
110
|
+
description: "Number of interventions per week",
|
|
111
|
+
},
|
|
112
|
+
frequency: {
|
|
113
|
+
type: "string",
|
|
114
|
+
enum: ["one_shot", "weekly", "bi_weekly", "monthly"],
|
|
115
|
+
},
|
|
116
|
+
prestation: {
|
|
117
|
+
type: "string",
|
|
118
|
+
enum: ["MENAGE"],
|
|
119
|
+
default: "MENAGE",
|
|
120
|
+
},
|
|
121
|
+
prestationInfo: {
|
|
122
|
+
type: "object",
|
|
123
|
+
properties: {
|
|
124
|
+
houseType: { type: "string" },
|
|
125
|
+
houseSize: { type: "integer" },
|
|
126
|
+
repassage: { type: "boolean" },
|
|
127
|
+
pets: {
|
|
128
|
+
type: "object",
|
|
129
|
+
properties: {
|
|
130
|
+
dog: { type: "boolean" },
|
|
131
|
+
cat: { type: "boolean" },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
comments: { type: "string" },
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: "create_booking",
|
|
142
|
+
description:
|
|
143
|
+
"Create a booking. Requires a quoteToken from get_quote plus the end-user's identity, address, and explicit consent. Returns a bookingToken (72h) for subsequent calls and a bookingId. The booking is held for 48h before worker dispatch as anti-fraud protection.",
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: "object",
|
|
146
|
+
required: [
|
|
147
|
+
"quoteToken",
|
|
148
|
+
"client",
|
|
149
|
+
"address",
|
|
150
|
+
"dateDebut",
|
|
151
|
+
"agentConsent",
|
|
152
|
+
],
|
|
153
|
+
properties: {
|
|
154
|
+
quoteToken: { type: "string" },
|
|
155
|
+
client: {
|
|
156
|
+
type: "object",
|
|
157
|
+
required: ["firstName", "lastName", "email", "phone"],
|
|
158
|
+
properties: {
|
|
159
|
+
firstName: { type: "string" },
|
|
160
|
+
lastName: { type: "string" },
|
|
161
|
+
email: { type: "string", format: "email" },
|
|
162
|
+
phone: { type: "string" },
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
address: {
|
|
166
|
+
type: "object",
|
|
167
|
+
required: ["street", "city", "zip"],
|
|
168
|
+
properties: {
|
|
169
|
+
street: { type: "string" },
|
|
170
|
+
city: { type: "string" },
|
|
171
|
+
zip: { type: "string", pattern: "^[0-9]{5}$" },
|
|
172
|
+
country: { type: "string", default: "France" },
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
dateDebut: {
|
|
176
|
+
type: "string",
|
|
177
|
+
format: "date-time",
|
|
178
|
+
description: "First intervention date (ISO 8601)",
|
|
179
|
+
},
|
|
180
|
+
frequency: {
|
|
181
|
+
type: "string",
|
|
182
|
+
enum: ["one_shot", "weekly", "bi_weekly", "monthly"],
|
|
183
|
+
},
|
|
184
|
+
nbHeuresSemaine: { type: "number" },
|
|
185
|
+
nbPrestaSemaine: { type: "integer", default: 1 },
|
|
186
|
+
comments: { type: "string" },
|
|
187
|
+
agentConsent: {
|
|
188
|
+
type: "boolean",
|
|
189
|
+
description:
|
|
190
|
+
"Attest that the end-user explicitly consented to share their data via your agent",
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "enroll_avance_immediate",
|
|
197
|
+
description:
|
|
198
|
+
"Enroll the end user with URSSAF for the 50% immediate tax credit advance. After this succeeds, the user pays only half the gross hourly rate via SEPA. Required: bookingToken from create_booking, full identity, birth place, postal address, IBAN.",
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: "object",
|
|
201
|
+
required: [
|
|
202
|
+
"bookingId",
|
|
203
|
+
"bookingToken",
|
|
204
|
+
"civilite",
|
|
205
|
+
"nomNaissance",
|
|
206
|
+
"prenoms",
|
|
207
|
+
"dateNaissance",
|
|
208
|
+
"lieuNaissance",
|
|
209
|
+
"numeroTelephonePortable",
|
|
210
|
+
"adresseMail",
|
|
211
|
+
"adressePostale",
|
|
212
|
+
"coordonneeBancaire",
|
|
213
|
+
],
|
|
214
|
+
properties: {
|
|
215
|
+
bookingId: { type: "string" },
|
|
216
|
+
bookingToken: { type: "string" },
|
|
217
|
+
civilite: {
|
|
218
|
+
type: "string",
|
|
219
|
+
enum: ["1", "2"],
|
|
220
|
+
description: "1=Monsieur, 2=Madame (NOT M/MME)",
|
|
221
|
+
},
|
|
222
|
+
nomNaissance: { type: "string" },
|
|
223
|
+
nomUsage: { type: "string" },
|
|
224
|
+
prenoms: { type: "string" },
|
|
225
|
+
dateNaissance: { type: "string", format: "date" },
|
|
226
|
+
lieuNaissance: {
|
|
227
|
+
type: "object",
|
|
228
|
+
properties: {
|
|
229
|
+
codePaysNaissance: { type: "string" },
|
|
230
|
+
departementNaissance: { type: "string" },
|
|
231
|
+
communeNaissance: {
|
|
232
|
+
type: "object",
|
|
233
|
+
properties: {
|
|
234
|
+
codeCommune: { type: "string" },
|
|
235
|
+
libelleCommune: { type: "string" },
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
numeroTelephonePortable: {
|
|
241
|
+
type: "string",
|
|
242
|
+
pattern: "^(0|\\+33)[6-7]([0-9]{2}){4}$",
|
|
243
|
+
},
|
|
244
|
+
adresseMail: { type: "string", format: "email" },
|
|
245
|
+
adressePostale: {
|
|
246
|
+
type: "object",
|
|
247
|
+
properties: {
|
|
248
|
+
libelleVoie: { type: "string" },
|
|
249
|
+
libelleCommune: { type: "string" },
|
|
250
|
+
codeCommune: { type: "string" },
|
|
251
|
+
codePostal: { type: "string" },
|
|
252
|
+
codePays: { type: "string" },
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
coordonneeBancaire: {
|
|
256
|
+
type: "object",
|
|
257
|
+
required: ["bic", "iban", "titulaire"],
|
|
258
|
+
properties: {
|
|
259
|
+
bic: { type: "string" },
|
|
260
|
+
iban: { type: "string" },
|
|
261
|
+
titulaire: { type: "string" },
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: "get_booking_status",
|
|
269
|
+
description:
|
|
270
|
+
"Poll the current status of a booking (order, mission, worker assignment, URSSAF enrollment). Requires bookingId + bookingToken from create_booking.",
|
|
271
|
+
inputSchema: {
|
|
272
|
+
type: "object",
|
|
273
|
+
required: ["bookingId", "bookingToken"],
|
|
274
|
+
properties: {
|
|
275
|
+
bookingId: { type: "string" },
|
|
276
|
+
bookingToken: { type: "string" },
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
283
|
+
tools: TOOLS,
|
|
284
|
+
}));
|
|
285
|
+
|
|
286
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
287
|
+
const { name, arguments: args } = request.params;
|
|
288
|
+
try {
|
|
289
|
+
let result;
|
|
290
|
+
switch (name) {
|
|
291
|
+
case "search_coverage": {
|
|
292
|
+
const qs = new URLSearchParams({
|
|
293
|
+
zip: args.zip,
|
|
294
|
+
prestation: args.prestation || "MENAGE",
|
|
295
|
+
});
|
|
296
|
+
result = await apiRequest(`/coverage?${qs.toString()}`);
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
case "get_quote": {
|
|
300
|
+
result = await apiRequest("/quote", {
|
|
301
|
+
method: "POST",
|
|
302
|
+
body: args,
|
|
303
|
+
});
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
case "create_booking": {
|
|
307
|
+
result = await apiRequest("/book", {
|
|
308
|
+
method: "POST",
|
|
309
|
+
body: args,
|
|
310
|
+
});
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
case "enroll_avance_immediate": {
|
|
314
|
+
const { bookingId, bookingToken, ...urssafPayload } = args;
|
|
315
|
+
result = await apiRequest(
|
|
316
|
+
`/booking/${bookingId}/enroll-urssaf`,
|
|
317
|
+
{
|
|
318
|
+
method: "POST",
|
|
319
|
+
body: urssafPayload,
|
|
320
|
+
bookingToken,
|
|
321
|
+
}
|
|
322
|
+
);
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
case "get_booking_status": {
|
|
326
|
+
const { bookingId, bookingToken } = args;
|
|
327
|
+
result = await apiRequest(`/booking/${bookingId}`, {
|
|
328
|
+
bookingToken,
|
|
329
|
+
});
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
default:
|
|
333
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
content: [
|
|
337
|
+
{
|
|
338
|
+
type: "text",
|
|
339
|
+
text: JSON.stringify(result, null, 2),
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
} catch (err) {
|
|
344
|
+
return {
|
|
345
|
+
isError: true,
|
|
346
|
+
content: [
|
|
347
|
+
{
|
|
348
|
+
type: "text",
|
|
349
|
+
text: `Error calling ${name}: ${err.message}${
|
|
350
|
+
err.details ? `\nDetails: ${JSON.stringify(err.details)}` : ""
|
|
351
|
+
}`,
|
|
352
|
+
},
|
|
353
|
+
],
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
const transport = new StdioServerTransport();
|
|
359
|
+
await server.connect(transport);
|
|
360
|
+
console.error("[@maideo/mcp] Server running on stdio");
|