anthropics / anthropics/claude-ai-mcp
Google Calendar MCP: create_event silently drops the location field (update_event sets it fine)
- Lenguaje dominante
- Sin datos de lenguaje
- Estrellas
- 471
- Forks
- 76
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Descripción
### What happened?
The Google Calendar connector's `create_event` tool declares a `location` parameter in its schema ("Optional. Location.", type string), accepts it without complaint, and returns a successful, fully-formed event — but the location is never persisted. The returned event object has no `location` key at all, and a follow-up `get_event` confirms the field was never written. The event shows up in the Google Calendar UI with an empty location.
There is no error, no warning, and no partial-success signal. The call looks like it worked.
### Differential test against an independent client
I created two events on the same calendar, same Google account, 4 seconds apart. One via this connector's `create_event`, one via a separate CLI client running locally under its own OAuth credentials. Then I read both events back with *both* clients:
| Event | Created by | `location` sent | Read by independent CLI | Read by this connector's `get_event` |
|---|---|---|---|---|
| A | **this connector** | `LOCATION-A-SHOULD-BE-HERE` | `""` | *(field absent)* |
| B | independent CLI | `LOCATION-B-SHOULD-BE-HERE` | `LOCATION-B-SHOULD-BE-HERE` | `LOCATION-B-SHOULD-BE-HERE` |
The bottom-right cell is the important one: **this connector reads event B's `location` back correctly.** Its read path and response serialization are demonstrably fine — it just never wrote the field on event A. And an independent client, on a different code path with separate credentials, confirms A's location is genuinely empty in Google, so this isn't the connector misreporting its own work.
The only variable between A and B is which client performed the insert.
### Other explanations ruled out
- **Not a scope or permission problem.** Calling `update_event` on the very same event, with the identical location string, persists it immediately and returns `"location": "Test Location 12345"` — same session, same token.
- **Not calendar-specific.** Reproduced on both the primary calendar and a secondary (shared, `@group.calendar.google.com`) calendar.
- **Not a general "optional fields are ignored" bug.** In the same `create_event` call I also passed `colorId`, `description` and `timeZone` — all three persisted correctly. `location` was the only field dropped.
- **Not an unsupported field at the API level.** Google's [`events.insert` reference](https://developers.google.com/workspace/calendar/api/v3/reference/events/insert) lists `location` (`string`, "Geographic location of the event as free-form text") as **writable** on `insert` — not update-only.
So the write path for `location` appears to be missing specifically in `create_event`, while `update_event` handles it correctly.
### What did you expect to happen?
`create_event` should persist `location` on the new event and include it in the returned event object, exactly as `update_event` does.
If for some reason location cannot be set at creation time, the call should fail with an explicit error — or at minimum return a warning — rather than reporting success while silently discarding a field it advertises in its own schema. A silent drop is the worst case here, because nothing downstream can detect it.
### Steps to reproduce
1. Connect the built-in Google Calendar connector in Claude.
2. Call `create_event`:
```json
{
"summary": "MCP bug repro - safe to delete",
"startTime": "2026-08-05T23:00:00",
"endTime": "2026-08-05T23:30:00",
"timeZone": "UTC",
"location": "Test Location 12345",
"colorId": "5",
"description": "Throwaway event."
}
```
3. The response is `"status": "confirmed"` and contains `colorId`, `description`, `start`, `end`, `summary` — **but no `location` key**.
4. Call `get_event` with the returned `eventId` → still no `location`. The Google Calendar UI shows the event with no location.
5. Call `update_event` with that same `eventId` and the identical `location` string → the response now contains `"location": "Test Location 12345"`.
Reproduced 100% of the time, on both primary and secondary calendars.
### Area
Tool Discovery / Invocation
### MCP Server (if applicable)
Google Calendar (built-in Anthropic connector) — tools create_event, update_event, get_event
### Error messages or logs
```shell
No error is emitted. Payloads below, trimmed and with identifiers redacted.
--- create_event REQUEST (secondary calendar) ---
{
"calendarId": "@group.calendar.google.com",
"summary": "MCP bug repro - safe to delete",
"startTime": "2026-08-05T23:00:00",
"endTime": "2026-08-05T23:30:00",
"timeZone": "UTC",
"location": "Test Location 12345",
"description": "Throwaway event."
}
--- create_event RESPONSE (note: no "location") ---
{
"id": "",
"status": "confirmed",
"summary": "MCP bug repro - safe to delete",
"description": "Throwaway event.",
"start": { "dateTime": "2026-08-05T23:00:00Z", "timeZone": "UTC" },
"end": { "dateTime": "2026-08-05T23:30:00Z", "timeZone": "UTC" },
"eventType": "DEFAULT",
"created": "2026-08-05T20:45:32Z"
}
--- get_event RESPONSE for the same eventId (still no "location") ---
{
"id": "",
"status": "confirmed",
"summary": "MCP bug repro - safe to delete",
...
}
--- create_event RESPONSE, primary calendar, same params + colorId: "5" ---
{
"id": "",
"colorId": "5", <-- optional field, persisted
"description": "Throwaway event on primary calendar.",
"status": "confirmed"
<-- no "location"
}
--- update_event REQUEST (same eventId, same string) ---
{ "eventId": "", "location": "Test Location 12345" }
--- update_event RESPONSE ---
{
"id": "",
"location": "Test Location 12345", <-- works
"status": "confirmed",
"updated": "2026-08-05T20:45:52Z"
}
=== DIFFERENTIAL TEST: same calendar, same account, 4 seconds apart ===
--- Event B, created by an INDEPENDENT CLI client (separate OAuth, separate code path) ---
{
"id": "",
"summary": "TEST B - made by independent client",
"location": "LOCATION-B-SHOULD-BE-HERE", <-- saved
"status": "confirmed",
"created": "2026-08-05T21:23:47.000Z"
}
--- Event A, created by THIS CONNECTOR with the same shape of request ---
{
"id": "",
"summary": "TEST A - made by Claude connector",
"status": "confirmed",
"created": "2026-08-05T21:23:51Z"
<-- no "location"
}
--- CROSS-READ 1: this connector's get_event reading event B ---
{
"id": "",
"summary": "TEST B - made by independent client",
"location": "LOCATION-B-SHOULD-BE-HERE" <-- connector READS location fine
}
--- CROSS-READ 2: independent CLI listing both events ---
{
"count": 2,
"events": [
{ "summary": "TEST A - made by Claude connector", "location": "" },
{ "summary": "TEST B - made by independent client", "location": "LOCATION-B-SHOULD-BE-HERE" }
]
}
```
### Additional context
**Impact.** Every event created through this connector loses its location. The only reliable workaround is create-then-update: call `create_event`, immediately call `update_event` with the same `eventId` and the same `location`, and verify `location` is present in the update response before treating the event as successfully created. That doubles the write calls on every single event and leaves a window in which the event exists on the calendar in a wrong state. Any caller that trusts the success response from `create_event` — as it reasonably should — silently produces events with missing locations.
The silence is the part that bites hardest — because `create_event` returns success and the schema advertises the parameter, nothing short of an explicit read-back catches it.
**This is not the same class of issue as the existing Calendar field requests — please don't triage it as one.** #28919 (`colorId`, added), #156 (`visibility`, open) and #191 (`reminders`, closed "not planned") are all *"this field is absent from the tool schema, please add support for it."* Those are feature requests, and a maintainer can reasonably decline them.
`location` is different: it **is** declared in the `create_event` schema, it **is** accepted without validation error, and the call **reports success** — the value is then discarded. Compare #191, where passing an unsupported field at least produced a loud, honest `Unknown name "reminders": Cannot find field`. That behavior is fine; a caller can see it and react. Here the tool advertises a parameter, takes it, says "confirmed," and drops it. Nothing downstream can detect the failure without an extra read-back. That is a broken contract between the schema and the implementation, not a missing capability.
If `location` genuinely isn't wired into the create path, the minimum correct fix is to reject it the way `reminders` is rejected. The right fix is to persist it, since `update_event` already does.
**Environment:** Claude desktop app, built-in Google Calendar connector, reproduced 2026-08-05.
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Evaluación
Este issue todavía no se ha evaluado.