Skip to main content
Glama
vamsi-1234

Office Booking MCP

by vamsi-1234

Office Booking MCP

A small, personal Model Context Protocol server and command-line tool that books and cancels your office cab and lunch from inside VS Code (or any MCP client) — or fully on autopilot — by wrapping the same APIs the company apps already use with your own logged-in account.

⚠️ Use responsibly. This only replays requests your own authenticated account is allowed to make. Don't share captured tokens, don't automate other people's accounts, and check your company's acceptable-use policy before relying on it. It is not affiliated with or endorsed by the app vendors.


What you get

Two ways to drive it:

  • MCP server — ask an LLM agent (e.g. Copilot Chat) in plain English: "book lunch for next Wednesday", "cancel Friday", "list my cab trips".

  • CLI (office-booking …) — the same actions from the terminal, also understands natural-language dates (book "next wednesday", book "this week").

Core tools:

Tool

What it does

list_cab_bookings

Show your current/upcoming cab trips

book_cab

Book a cab

cancel_cab

Cancel a cab trip

list_lunch_bookings

Show your lunch bookings

book_lunch

Book lunch for a date

cancel_lunch

Cancel a lunch booking

Hands-off extras (lunch):

  • 📅 Attendance schedule — encode your rotating hybrid pattern (e.g. a 3-day week alternating with a 2-day week); it books only the days you're actually in.

  • 🏖️ Outlook leave detection — reads your Outlook calendar and skips any day marked Out of Office or titled like leave/PTO/vacation.

  • 📧 Daily QR delivery by email — emails you the day's lunch QR, then deletes it again in the evening via IMAP so your inbox stays clean.

  • 💻 Wake-triggered auto-booking — a macOS launchd job books every upcoming office day inside the cafeteria's advance window whenever your Mac is awake (no fixed alarms; idempotent, so it just tops up what's missing).

The endpoints are not hard-coded to your company — the project ships with placeholder paths/payloads marked TODO. You fill them in once, using the traffic you capture in Step 1.


Related MCP server: Microsoft MCP

Step 1 — Capture the APIs

Easiest path first: use the web app. If your cab/lunch service has a web portal, capture it there — open the site in your browser, press F12 → Network tab, perform each action once, and copy the requests (right-click → Copy as cURL). There's no certificate setup and no TLS pinning to fight, so it's dramatically simpler than intercepting a phone. The project even ships a curl_to_config helper to turn a pasted cURL command into config. Only fall back to the mobile-proxy steps below if there is no web version.

If the service is mobile-only, intercept its HTTPS traffic with a proxy. mitmproxy is free and works well.

1a. Install + start mitmproxy

brew install mitmproxy        # macOS
mitmweb                       # opens a web UI at http://127.0.0.1:8081

mitmproxy listens on port 8080 by default.

1b. Point your phone at the proxy

  1. Put your phone and Mac on the same Wi-Fi.

  2. Find your Mac's IP: ipconfig getifaddr en0.

  3. On the phone: Wi-Fi → (your network) → Configure Proxy → Manual, server = your Mac IP, port = 8080.

1c. Install mitmproxy's CA certificate on the phone

  1. On the phone's browser open http://mitm.it and install the cert for your OS.

  2. iOS: Settings → General → VPN & Device Management → install the profile, then Settings → General → About → Certificate Trust Settings and toggle it on. (Both steps are required.)

  3. Android: install under user certificates (system store needs root).

1d. The TLS-pinning gotcha ⚠️

Many corporate apps use certificate pinning and will refuse to connect while proxied — you'll see connection errors in the app and TLS errors in mitmproxy.

Things to try, in order of effort:

  • Check if there's a web version (the recommended path — see the tip at the top of Step 1). Capturing the web portal in browser DevTools avoids pinning entirely and is by far the easiest option.

  • See whether the app still works for some calls (login may be pinned but booking may not).

  • On a rooted Android / jailbroken iOS you can disable pinning with Frida + objection, but that's advanced and may violate device/app policy — only do it on a device you own and are allowed to modify.

If pinning fully blocks you, the web portal route is by far the most practical.

1e. Record each action

With capturing live, perform each action once in the app: list trips, book a cab, cancel it, list lunch, book lunch, cancel it. For each captured request note:

  • Host (e.g. cab-api.yourcompany.com) → goes in *_API_BASE_URL

  • HTTP method + path (e.g. POST /api/v1/trips)

  • Auth header (e.g. Authorization: Bearer eyJ...) → token goes in *_AUTH_TOKEN

  • Any extra header like x-api-key*_API_KEY

  • The request body (JSON) and the response body


Step 2 — Fill in the endpoints

Open these two files and replace the TODO placeholders with what you captured:

  • src/office_mcp/cab_client.py

  • src/office_mcp/lunch_client.py

You're adjusting three things per method: the HTTP method, the path, and the JSON field names. The auth headers are handled centrally in src/office_mcp/http_client.py (_default_headers) — tweak there if your app doesn't use Authorization: Bearer.


Step 3 — Configure secrets

cp .env.example .env

Fill in the base URLs and tokens you captured. .env is git-ignored, so your tokens stay local.

🔑 Tokens often expire. When a tool starts returning HTTP 401, re-capture a fresh token and update .env.


Step 4 — Install & run

python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Sanity-check it starts (Ctrl-C to stop):

python -m office_mcp.server

Step 5 — Use it in VS Code

This repo includes .vscode/mcp.json, so VS Code will offer to start the office-booking server. Open the Copilot Chat Agent mode, and you can ask things like:

  • "List my cab bookings."

  • "Book a cab from Home to Office tomorrow at 9:30am."

  • "Cancel lunch order 12345."

Enable debug logging by setting OFFICE_MCP_DEBUG=true in .env to see the exact outgoing requests in the server's stderr.


Step 6 — (Optional) CLI & hands-off automation

The same actions are available from the terminal via the office-booking command (installed by pip install -e .):

office-booking lunch list
office-booking lunch book "next wednesday"     # natural-language dates
office-booking lunch cancel <order-id>
office-booking lunch qr 23-06-2026             # generate a booking's QR

Lunch automation commands:

office-booking schedule set      # record your rotating office-attendance pattern
office-booking lunch auto-book    # book upcoming office days in the advance window
office-booking lunch qr-deliver   # email today's QR to yourself
office-booking lunch qr-cleanup   # delete that QR email via IMAP

These are designed to run unattended on macOS via launchd agents (~/Library/LaunchAgents/com.officebooking.*.plist):

  • auto-book — runs whenever the Mac wakes (RunAtLoad + a periodic StartInterval); idempotent, so it simply books any still-unbooked office day inside the cafeteria's advance window and skips leave days.

  • qr-deliver / qr-cleanup — fixed weekday times; if the Mac is asleep at the scheduled time, launchd runs the missed job shortly after the Mac wakes.

All of these honour the attendance schedule and Outlook leave detection, so you only ever get booked for days you're actually in the office.


Project layout

src/office_mcp/
  config.py        # loads settings from .env (no secrets in code)
  http_client.py   # auth + request plumbing, error handling
  cab_client.py    # cab endpoints  ← fill in TODOs
  lunch_client.py  # lunch endpoints ← fill in TODOs
  server.py        # MCP server: the booking tools
  cli.py           # `office-booking` command-line interface
  dates.py         # natural-language date parsing
  attendance.py    # rotating office-attendance schedule
  outlook_leave.py # reads Outlook for Out-of-Office / leave days
  mailer.py        # SMTP send + IMAP delete for daily QR delivery
  qrcode.py        # QR image generation
  curl_to_config.py# turn a pasted cURL command into config
  update_token.py  # refresh an expired auth token in .env
.vscode/mcp.json   # VS Code MCP server registration
.env.example       # copy to .env and fill in

Security notes

  • Secrets live only in .env (git-ignored) — never commit real tokens.

  • The server makes outbound calls only to the hosts you configure.

  • If you push this to a repo, double-check no capture files (captures/, *.flow), .env, or personal data (office_schedule.json, QR PNGs) slipped in. The included .gitignore already excludes all of these.

Available Tools

6 tools
book_cabA

Book an office cab.

Args: pickup: Pickup location (address or saved place name). drop: Drop-off location. when: When the cab is needed, ISO 8601 e.g. "2026-06-18T09:30:00". notes: Optional note for the driver/admin.

ParametersJSON Schema
NameRequiredDescriptionDefault
pickupYes
dropYes
whenYes
notesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavioral traits. It only states that the tool books a cab, without mentioning any side effects, authentication requirements, or confirmation behavior. This lacks transparency for a mutation action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured with an Args section. Every sentence adds value, and there is no superfluous information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that an output schema exists and parameters are well described, the description is mostly complete. It could mention prerequisites like user login or cab availability, but the core functionality is sufficiently covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the schema by providing context for each parameter: pickup location type, drop location, ISO 8601 format for when, and clarification that notes are optional. This compensates for the 0% schema description coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with 'Book an office cab,' which is a clear verb+resource combination. It immediately distinguishes this tool from siblings like cancel_cab and list_cab_bookings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage through parameter explanations but does not explicitly state when to use this tool versus alternatives like book_lunch or cancel_cab. However, the context of cab vs lunch is clear from the tool name and siblings list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

book_lunchB

Book office lunch for a date.

Args: date: Slot date as DD-MM-YYYY, e.g. "23-06-2026". time: Slot time as HH:MM (defaults to the captured slot time). food_id: Optional item id to order; if empty, books the template's item. food_name: Optional human-readable name for that item. price: Optional unit price for that item (0 = keep template price). veg: Whether the item is vegetarian. quantity: Number of units (default 1).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
timeNo20:13
food_idNo
food_nameNo
priceNo
vegNo
quantityNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully disclose behavior. It only explains parameters and does not mention side effects (e.g., whether booking overwrites an existing one), required permissions, or other behavioral traits like idempotency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a leading sentence and a list of arguments. However, it is somewhat verbose (8 lines) and could be more concise by merging some parameter explanations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (7 parameters, 1 required) and existence of an output schema, the description adequately covers parameter semantics but lacks behavioral context such as success/error outcomes, idempotency, or constraints (e.g., lunch must be in the future).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description compensates for the 0% schema description coverage by explaining each parameter in detail, including format examples (e.g., date as DD-MM-YYYY) and notes on defaults (e.g., price of 0 keeps template price). This adds significant meaning beyond the schema's bare types and titles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Book office lunch for a date,' specifying the verb and resource. However, it does not explicitly differentiate from siblings like 'book_cab' or 'cancel_lunch', which would strengthen purpose clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus its siblings (e.g., cancel_lunch, list_lunch_bookings). There is no mention of prerequisites, constraints, or scenarios where the tool should not be used.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_cabA

Cancel an office cab booking.

Args: booking_id: The id of the trip to cancel (from list_cab_bookings). reason: Optional cancellation reason.

ParametersJSON Schema
NameRequiredDescriptionDefault
booking_idYes
reasonNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully disclose behavior. It only says 'Cancel', implying a state change, but does not describe side effects (e.g., refunds, reversibility), permissions required, rate limits, or endpoint behavior. The output schema exists but is not referenced to clarify return values.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: one line for purpose, then a docstring-style argument list. Every sentence adds value, no fluff. The key information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with 2 parameters and an output schema, the description covers the basic purpose and parameter sources. However, it lacks details on error handling, idempotency, or response structure, which are helpful for an agent to fully understand the tool's behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description adds essential meaning: booking_id is the trip ID from list_cab_bookings, and reason is optional. This clarifies the source and intent of parameters beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Cancel an office cab booking', specifying the verb (cancel) and the resource (cab booking). This distinguishes it from siblings like cancel_lunch and book_cab, which are different tools for different actions or resources.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains that the booking_id comes from list_cab_bookings, giving clear context on the prerequisite. However, it does not explicitly state when not to use this tool (e.g., if the booking is already cancelled) or provide alternatives beyond the sibling tool context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_lunchA

Cancel an office lunch booking.

Args: booking_id: The id of the lunch order to cancel (from list_lunch_bookings). reason: Optional cancellation reason.

ParametersJSON Schema
NameRequiredDescriptionDefault
booking_idYes
reasonNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided. Description only states 'cancel' with no details on side effects, permissions, or irreversibility. Lacks behavioral context beyond the action itself.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise: one-line purpose and parameter list. Front-loaded, no extraneous text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists so return values not needed. However, lacks behavioral details (e.g., reversibility, confirmation) for a cancel action. Minimal but functional.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, description adds meaning: booking_id sourced from list_lunch_bookings, reason is optional. Compensates for missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb 'cancel' and resource 'lunch booking', distinctly different from sibling tools like 'book_lunch' and 'cancel_cab'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States that booking_id comes from 'list_lunch_bookings', providing implicit guidance on prerequisite action. No explicit when-not-to-use, but clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_cab_bookingsA

List your current and upcoming office cab bookings.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It mentions 'current and upcoming' bookings but does not disclose other behaviors like pagination or data recency. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that is clear and concise, with no unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no parameters and an output schema present, the description provides adequate scope ('current and upcoming'). It is complete for this simple list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has no parameters, so schema coverage is complete. Baseline score of 4 is appropriate as no additional parameter information is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'List' and the resource 'office cab bookings'. It distinguishes from sibling tools like list_lunch_bookings and book_cab/cancel_cab by specifying 'cab bookings' and 'current and upcoming'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives like list_lunch_bookings. The usage context is implied but not stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_lunch_bookingsA

List your current and upcoming office lunch bookings.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully convey behavioral traits. It indicates read-only and personal scope but doesn't clarify safety (side effects), rate limits, or what 'current and upcoming' exactly means (e.g., does it exclude past bookings?).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no unnecessary words. Every part adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (no parameters, list-only operation) and the presence of an output schema, the description is nearly complete. It could be improved by noting ordering or time range, but adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has zero parameters, so baseline 4 applies. The description adds no parameter info (none needed), but clearly states the tool's purpose. Schema coverage is 100% trivially.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and clearly identifies the resource ('your current and upcoming office lunch bookings'). It distinguishes from sibling tools like book_lunch and list_cab_bookings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use for viewing personal bookings, but lacks explicit guidance on when to use versus alternatives (e.g., site-wide booking reports) or when not to use. No exclusions or context provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.1.0
    • First observedbook_cab
    • First observedbook_lunch
    • First observedcancel_cab
    • First observedcancel_lunch
    • First observedlist_cab_bookings
    • First observedlist_lunch_bookings

TDQS

A3.8/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct resource (cab or lunch) and action (book, cancel, list), with no overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (e.g., book_cab, cancel_lunch), making them predictable and easy to understand.

Tool Count5/5

With 6 tools covering two services with three operations each, the count is well-scoped and appropriate for the domain.

Completeness3/5

The set covers create, cancel, and list for both services, but lacks update/modify functionality, requiring users to cancel and rebook for changes, which is a notable gap.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers