ics-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ics-mcpwhat's on my calendar today?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ics-mcp
A tiny, read-only Model Context Protocol
(MCP) server that exposes an iCalendar (.ics) feed as calendar-query tools.
It is designed for published calendar URLs — for example an Outlook /
Exchange Online calendar shared via Publish calendar → ICS link, or any other
webcal/https .ics feed. Because it consumes an anonymous published feed,
it needs no OAuth, no app registration, and no admin consent — which makes
it a practical way to give an AI assistant read access to a Microsoft 365
calendar when Microsoft Graph admin consent is not available.
Recurring events are expanded into individual occurrences on query.
Read-only by design. There are no tools that create, modify, or delete events. The server only ever performs HTTP GETs against the feed URL.
Tools
Tool | Description |
| Events between two dates/times. Accepts |
| Everything happening today. |
| Events from now through the next N days (1–90). |
| Case-insensitive substring match over title, location, organizer, attendees, and description. |
| Feed name, timezone, master event count, cache TTL. |
Related MCP server: ical-mcp
Configuration
All configuration is via environment variables:
Variable | Required | Default | Description |
| yes | — |
|
| no |
| Friendly name reported in tool output. |
| no | system local | IANA tz (e.g. |
| no |
| Seconds to cache the fetched feed between refreshes. |
| no |
| Feed fetch timeout, in seconds. |
Usage
Run with uvx (no install)
ICS_URL="https://outlook.office365.com/owa/calendar/<id>/calendar.ics" \
uvx --from git+https://github.com/mieweb/ics-mcp ics-mcpopencode / Claude Desktop MCP config
{
"mcp": {
"ics_calendar": {
"type": "local",
"command": [
"uvx",
"--from",
"git+https://github.com/mieweb/ics-mcp",
"ics-mcp"
],
"environment": {
"ICS_URL": "https://outlook.office365.com/owa/calendar/<id>/calendar.ics",
"ICS_CALENDAR_NAME": "My Calendar",
"ICS_TIMEZONE": "America/New_York"
}
}
}
}(Claude Desktop uses the same shape under mcpServers with command +
args split out.)
Getting a published ICS URL from Outlook / Microsoft 365
Open Outlook on the web → Settings → Calendar → Shared calendars.
Under Publish a calendar, pick the calendar and a permission level (Can view all details for full event info).
Click Publish, then copy the ICS link (not the HTML link).
Use that URL as
ICS_URL.
Anyone with the published ICS link can read the calendar, so treat the URL as a
secret and keep it out of source control (pass it via environment, as above).
Development
git clone https://github.com/mieweb/ics-mcp
cd ics-mcp
ICS_URL="file:///path/to/calendar.ics" uv run ics-mcpLicense
MIT © Medical Informatics Engineering
Available Tools
5 toolsget_calendar_infoB
Report basic information about the configured calendar feed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It implies a read-only report of a 'configured' feed but says nothing about auth requirements, rate limits, or what happens when no feed is configured. The output schema covers return values, which limits the gap somewhat.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with no filler. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter metadata getter with an output schema documenting the return, the description is largely sufficient. Its only shortfall is not flagging prerequisites (e.g., the feed must be configured) despite no annotations being present to cover that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 per the rubric. No parameter description is needed or expected here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Report') and resource ('basic information about the configured calendar feed'), clearly distinguishing it from the event-listing siblings. The only weakness is that 'basic information' is vague about which fields are returned, but the resource boundary is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to call this versus list_events, list_today, list_upcoming, or search_events. The agent must infer that this is the metadata/feed-config tool rather than an event query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsA
List calendar events between two dates/times (inclusive).
Recurring events are expanded into individual occurrences. Accepts natural values like "today"/"tomorrow", ISO dates ("2026-01-15"), or full timestamps. A bare end date covers the entire day.
Args: start: Range start (e.g. "today", "2026-01-15", "2026-01-15T09:00"). end: Range end (e.g. "2026-01-22"). include_description: Include the full event body text. Default False.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| start | Yes | ||
| include_description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it delivers meaningful behavioral detail: recurring events are expanded into occurrences, the range is inclusive, and a bare end date covers the entire day. It stops short of disclosing pagination limits, sort order, or timezone handling, so it is strong but not complete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then behavioral notes, then an Args block. Minor redundancy where value formats are listed in prose and then repeated in the Args section, but overall efficient and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. The description covers formats, recurrence expansion, and day-boundary semantics, which is most of what an agent needs. Gaps around timezone, result ordering, and any result limits keep it from a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and the Args block documents all three parameters: start and end with concrete format examples ('today', ISO dates, timestamps) and include_description with its default. It adds real meaning over the bare schema types, though end only gets one example and formats could be tied to parameters more precisely.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (calendar events) with an explicit scope ('between two dates/times, inclusive'), which distinguishes it from list_today and list_upcoming. It does not explicitly name those siblings or search_events, so it falls short of a 5, but the range-based framing makes the distinction inferable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the date-range framing (use when you need an arbitrary window), and accepted value formats are clarified. However, there is no explicit guidance on when to prefer this over list_today, list_upcoming, or search_events, and no exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_todayB
List all events occurring today (in the calendar's local timezone).
| Name | Required | Description | Default |
|---|---|---|---|
| include_description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It does add one useful behavioral detail, the calendar's local timezone semantics for 'today', but says nothing about permissions, result limits, or ordering. An output schema exists, so return shape is covered elsewhere.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with the scope qualifier in parentheses; no wasted text. It is appropriately terse for a simple list tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and low complexity (one optional boolean), the description is close to adequate, but the undocumented parameter and absence of any usage framing leave meaningful gaps for an agent choosing among calendar siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter (include_description) with 0% schema description coverage and a default of false, and the description never mentions it. With coverage below 50% the description should compensate, but it adds no meaning about what this flag does or when to set it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) plus resource (events) and a clear temporal scope (occurring today), which differentiates it from list_events and list_upcoming. It does not explicitly name those siblings, so the differentiation relies on the reader noticing the 'today' scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'today' scope implies when to reach for this tool, but there is no explicit when-to-use/when-not guidance and no reference to the alternatives (list_events, list_upcoming, search_events). Usage is only inferable from the name and scope.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_upcomingA
List events from now through the next N days.
Args: days: How many days ahead to include (1-90). Default 7. include_description: Include the full event body text. Default False.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| include_description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it only partially delivers: it discloses the day-range bound (1-90) and the meaning of include_description, which is genuinely useful behavioral context. It says nothing about ordering, pagination, or permissions, though a read-only listing tool is low risk.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded in one sentence and the Args block is tight, with no filler. The raw docstring 'Args:' formatting is slightly informal for a description but costs little.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and both parameters are fully documented for a two-param list tool. The remaining gap is sibling routing rather than anything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% (only titles, no descriptions), so the description must compensate and it does: it defines days as a look-ahead window bounded 1-90 with default 7, and include_description as pulling the full event body with default False. Both parameters gain full meaning absent from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (events) with a clear scope: 'from now through the next N days'. It does not differentiate from siblings like list_today or list_events, which overlap in scope, so an agent still has to guess which to pick.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies a forward-looking range but never says when to use this over list_events, list_today, or search_events. No alternatives or exclusions are named, leaving routing entirely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_eventsB
Search events whose title, location, organizer, or description matches a case-insensitive substring.
Args: query: Text to look for. start: Optional range start. Defaults to 30 days ago. end: Optional range end. Defaults to 180 days ahead. include_description: Include full body text in results. Default False.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ||
| query | Yes | ||
| start | No | ||
| include_description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does disclose useful traits: matching semantics (case-insensitive substring), the fields searched, the default time window (30 days back to 180 days forward), and that include_description controls whether body text is returned. It does not disclose result limits, sorting, pagination, or the accepted format for start/end strings.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence front-loads the core purpose, and the Args block is compact and scannable. Nothing is wasted, though the default values are repeated from the schema and the stop/end format gap means the space could have been used more information-densely.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value explanation is unnecessary and correctly omitted. However, for a search tool with no annotations, missing start/end format, result limits, ordering, and the search-vs-list relationship to siblings leaves real gaps for an agent trying to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it largely does: it explains that query is matched text, that start/end are optional range bounds with concrete defaults (30 days ago, 180 days ahead), and that include_description defaults to False. The one gap is that start/end formats (e.g., ISO 8601) are not specified despite being typed only as generic strings.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (search) and resource (events) and enumerates the matched fields (title, location, organizer, description) plus matching semantics (case-insensitive substring). It is clear what the tool does, but it never distinguishes itself from siblings like list_events or list_upcoming, leaving the search-vs-list choice implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance, and no mention of the sibling tools (list_events, list_upcoming, list_today) that overlap in purpose. The only usage signal is the word 'search' in the name and description, which an agent must infer means filtered lookup rather than enumeration.
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.
5 tool updates
v0.1.0- First observed
get_calendar_info - First observed
list_events - First observed
list_today - First observed
list_upcoming - First observed
search_events
TDQS
Scored across 5 tools
list_events, list_today, and list_upcoming all retrieve events and are essentially conveniences over the same underlying range query, so boundaries overlap slightly. However, each has a clearly documented default range/purpose, making selection reasonably predictable.
All names follow a consistent snake_case verb_noun pattern: list_events, list_today, list_upcoming, search_events, get_calendar_info. No mixing of conventions.
Five tools is well-scoped for a read-only ICS calendar feed, with each tool earning its place and no redundancy beyond the intentional convenience listers.
The domain is a read-only ICS feed, so no create/update/delete is expected. Listing (by range, today, upcoming), searching, and calendar metadata cover the realistic surface with no dead ends.
Maintenance
Related MCP Connectors
MCP server for Cronofy — read calendars, events and free/busy, and create, update or delete events.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
A MCP server that works with Google Calendar to manage event listing, reading, and updates.
Streamable HTTP MCP server for Google Calendar and Sheets with OAuth login.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA read-only MCP server that exposes iCalendar feeds as queryable tools for LLM agents, enabling calendar event retrieval and filtering.MIT
- AlicenseAqualityBmaintenanceMCP server for Apple Calendar and CalDAV providers. Enables listing, creating, updating, deleting events, and checking free/busy status with per-calendar write protection.6MIT
- FlicenseNot gradedqualityCmaintenanceMCP server for the Teamup Calendar API, enabling event management, calendar listing, and available slot search.-
- FlicenseDqualityDmaintenanceMCP server for interacting with Google Calendar, enabling reading events from public calendars and, with OAuth, creating, updating, and deleting events.1-