Skip to main content
Glama

End of Life

CI npm downloads OpenSSF Scorecard License: MIT

Is this version still supported? End of Life reads a project's Dockerfile, version files, manifests and CI workflows, finds every runtime, database and OS version it pins, and says for each: still supported, security fixes only, paid extended support only, or end of life, with the dates, the days left, the latest patch, the newest version to move to, and the smallest jump that still gets fixes.

Coding agents pick versions from memory: they write FROM node:18 or python-version: "3.8" years after those stopped getting security fixes. This server answers from endoflife.date (470+ products) and finds versions where they hide: python:3.8-slim-bullseye is Python 3.8 on Debian 11, node:18-alpine3.17 carries Alpine 3.17, .nvmrc may say lts/hydrogen (Node.js 18), runs-on: ubuntu-20.04 pins an OS.

Status

Meaning

supported

Regular fixes

security_only

Active support ended; security fixes continue

extended_only

End of life for most users; paid extended support continues

end_of_life

No fixes of any kind

upcoming

Not released yet

Status is computed from the dates on the day you ask, not from stored flags. For a range (>=3.8, ^18.12), the lowest version it allows is checked: it is the oldest version the project still promises to run on.

No account or key needed. Built and maintained by Arhan Canli.

Install

Install in Cursor Install in VS Code Install in Goose

Needs Node.js 20 or newer. No account or key.

Claude Code

claude mcp add end-of-life -- npx -y end-of-life-mcp

Claude Desktop: download end-of-life-mcp-<version>.mcpb from the latest release and open it. The bundle is signed; verify it with gh attestation verify <file> --repo arhancanli/end-of-life-mcp.

Any other client (Windsurf, Zed, Cline, Continue and others), in its MCP config file:

{
  "mcpServers": {
    "end-of-life": {
      "command": "npx",
      "args": [
        "-y",
        "end-of-life-mcp"
      ]
    }
  }
}

Docker

docker build -t end-of-life-mcp https://github.com/arhancanli/end-of-life-mcp.git && docker run -i --rm end-of-life-mcp

Hosted (Streamable HTTP): node src/server.mjs --http serves stateless MCP at POST /mcp (port from PORT, default 3000).

Related MCP server: CanIUse MCP

Example

An agent calls check_project with:

{
  "files": [
    {
      "path": "Dockerfile",
      "content": "FROM node:18-alpine3.17 AS build\nFROM python:3.8-slim-bullseye\n"
    },
    {
      "path": ".nvmrc",
      "content": "lts/hydrogen\n"
    },
    {
      "path": ".github/workflows/ci.yml",
      "content": "jobs:\n  test:\n    runs-on: ubuntu-20.04\n    strategy:\n      matrix:\n        node: [20, 22, 24]\n"
    },
    {
      "path": "pyproject.toml",
      "content": "[project]\nrequires-python = \">=3.10\"\n"
    },
    {
      "path": "README.md",
      "content": "hello"
    }
  ]
}

and gets back (recorded from the live server on 2026-09-26):

{
  "counts": {
    "end_of_life": 5,
    "extended_only": 2,
    "security_only": 2,
    "supported": 1
  },
  "results": [
    {
      "product": "nodejs",
      "version": "18",
      "cycle": "18",
      "status": "end_of_life",
      "lts": true,
      "eol": "2025-04-30",
      "active_until": "2023-10-18",
      "latest": "18.20.8",
      "link": "https://endoflife.date/nodejs",
      "upgrade_to": {
        "cycle": "24",
        "latest": "24.21.0",
        "lts": true
      },
      "nearest_supported": {
        "cycle": "22",
        "latest": "22.23.3",
        "eol": "2027-04-30"
      },
      "file": "Dockerfile",
      "line": 1,
      "found": "FROM node:18-alpine3.17 AS build"
    },
    {
      "product": "alpine-linux",
      "version": "3.17",
      "cycle": "3.17",
      "status": "end_of_life",
      "eol": "2024-11-22",
      "latest": "3.17.10",
      "link": "https://endoflife.date/alpine-linux",
      "upgrade_to": {
        "cycle": "3.24",
        "latest": "3.24.2"
      },
      "nearest_supported": {
        "cycle": "3.21",
        "latest": "3.21.8",
        "eol": "2026-11-01"
      },
      "file": "Dockerfile",
      "line": 1,
      "found": "FROM node:18-alpine3.17 AS build"
    },
    {
      "product": "python",
      "version": "3.8",
      "cycle": "3.8",
      "status": "end_of_life",
      "eol": "2024-10-07",
      "active_until": "2021-05-03",
... (176 more lines)

Tools

Tool

What it does

check_project

Finds the runtime, database and OS versions a project pins in its files (Dockerfile, .nvmrc, .node-version, .python-version, .ruby-version, runtime.txt, .tool-versions, package.json, pyproject.toml, go.mod, composer.json, Gemfile, global.json and GitHub Actions workflows) and checks each against endoflife.date, with file and line. Pass each file's path and text.

check_versions

Checks up to 50 'product version' pairs (python 3.8, node@18, postgres:13, ubuntu 20.04, django 4.2) against endoflife.date: status (supported, security_only, extended_only, end_of_life, upcoming), end-of-life date, days left, latest patch and the version to upgrade to. Worst first.

product_lifecycle

Every maintained release cycle of a product (and the most recent ended ones) with status, release, end-of-active-support and end-of-life dates, LTS flag and latest patch, plus the recommended upgrade target.

Files check_project reads: Dockerfile and Containerfile (FROM lines, including the OS in tags such as -alpine3.19 and -bookworm), .nvmrc, .node-version, .python-version, .ruby-version, runtime.txt, .tool-versions, package.json (engines, volta), pyproject.toml (requires-python, Poetry), go.mod (go, toolchain), composer.json, Gemfile, global.json and GitHub Actions workflows (setup-* versions, matrices, runs-on).

How it behaves

  • Read-only: no tool changes anything outside this process; files are read as text, never run.

  • Network: HTTPS only, to the hosts listed in package.json under factory.allowHosts, with a deadline, a size cap and bounded retries; a stalled read is retried. Nothing else is contacted, and nothing is logged except unexpected failures (to stderr, without your inputs).

  • Answers are cached for 12 hours.

  • Results are compact JSON with a matching output schema, worst status first.

Benchmark

Not yet measured.

Performance

Measured 2026-09-26 from Dubai, home connection against the live upstream, Node 24.19.0 (bench/perf.json, scripts/perf.mjs in the factory).

Call

First call

Repeat

Result size

check_project: Dockerfile, .nvmrc, a CI workflow, pyproject

1853 ms

2.6 ms

3,869 chars

check_versions: 6 named versions

2154 ms

3.1 ms

1,694 chars

product_lifecycle: Node.js

892 ms

1.2 ms

997 chars

First call: a fresh server process, including the TLS connection and the upstream's own time. Repeat: the same call again, answered from the in-process cache, so it shows this server's own overhead.

Tool definitions the model reads on every turn (name, description, input schema): 1,706 characters, against 6,734 for endoflife-mcp, the only published end-of-life server. The full tool list, with the output schemas and annotations clients use to validate results, is 3,165 characters (8,958 for the alternative).

Data sources

  • endoflife.date, the community-maintained end-of-life database (MIT-licensed). Confirm dates that matter commercially with the vendor.

More MCP servers by Arhan Canli

  • Internet Standards: RFC sections, status, obsoleted-by chains, errata and IANA registries for coding agents.

  • Package Truth: Checks packages exist before install: version, deprecation, vulnerabilities, licence. 7 ecosystems.

  • Citation Check: Verifies citations: finds fabricated or mismatched references and retractions, returns clean BibTeX.

  • Drug Label: FDA drug label answers with section citations, RxNorm name resolution, recalls and shortages.

  • Recall Check: One recall check across CPSC, FDA and NHTSA: match by name, model number, UPC or VIN.

  • Satellite Imagery: Find the clearest Sentinel-2, Landsat, Sentinel-1 or NAIP scene for any place, with band links.

  • The whole collection

License

MIT, Copyright (c) 2026 Arhan Canli.

Available Tools

3 tools
check_projectCheck a project's runtimesA
Read-onlyIdempotent

Finds the runtime, database and OS versions a project pins in its files (Dockerfile, .nvmrc, .node-version, .python-version, .ruby-version, runtime.txt, .tool-versions, package.json, pyproject.toml, go.mod, composer.json, Gemfile, global.json and GitHub Actions workflows) and checks each against endoflife.date, with file and line. Pass each file's path and text.

ParametersJSON Schema
NameRequiredDescriptionDefault
filesYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
countsYes
resultsYes

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, and the description adds concrete behavioral detail: it scans a specific set of file types and reports matches with file and line. It also clarifies that the caller must supply the file text rather than the tool reading paths, which is valuable beyond the annotations.

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

Conciseness4/5

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

The description is a long sentence but every part earns its place: the action, the supported file list, the output granularity, and the invocation requirement. It could be split for readability, but there is no fluff or redundancy.

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?

For a tool with this complexity, the description covers the input format, supported file types, what is checked, and the output detail. The output schema exists, so return values do not need to be spelled out. The main missing piece is differentiation from sibling tools, but that is not required for a correct call.

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

Parameters3/5

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. It maps 'path and text' to the path/content structure and lists relevant file types, which adds meaning beyond the bare schema. However, it does not clarify constraints like 30-file limits or that content should be the full file text, so the compensation is only partial.

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 states a clear action: it finds runtime, database, and OS versions pinned in project files and checks each against endoflife.date, returning file and line. It names the supported file types explicitly. It does not explicitly differentiate itself from siblings check_versions and product_lifecycle, so it misses the top score.

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?

There is no guidance on when to use this tool versus check_versions or product_lifecycle, and no exclusions or prerequisites are stated. The only usage-related instruction is 'Pass each file's path and text,' which is about invocation, not selection context.

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

check_versionsCheck versions for end of lifeA
Read-onlyIdempotent

Checks up to 50 'product version' pairs (python 3.8, node@18, postgres:13, ubuntu 20.04, django 4.2) against endoflife.date: status (supported, security_only, extended_only, end_of_life, upcoming), end-of-life date, days left, latest patch and the version to upgrade to. Worst first.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
countsYes
resultsYes

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already carry readOnly=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false. The description goes beyond those by disclosing the external data source (endoflife.date), the 'up to 50' cap, the returned status vocabulary, and the 'worst first' ordering behavior. That adds meaningful operational context without contradicting any annotation.

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, information-dense sentence with no filler. It front-loads the key limit ('up to 50') and immediately gives representative inputs, followed by output fields and ordering. Every phrase earns its place.

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 (so return values are documented elsewhere) and annotations cover safety, the description supplies the remaining essentials: input limits, input format examples, external source, and sort order. The only gap is usage routing among siblings, but that affects selection more than invocation, so the tool itself is adequately described.

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 schema description coverage at 0%, the description must explain the 'items' parameter, and it does by giving five concrete examples of product-version pairs (python 3.8, node@18, postgres:13, ubuntu 20.04, django 4.2). This conveys both the value type and the variety of accepted formats, though it stops short of an explicit grammar, so it is not a full 5.

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 names a specific verb ('Checks') and a precise resource ('product version pairs against endoflife.date'), and lists the concrete outputs (status, EOL date, days left, patch, upgrade target). It is clear on its own, but it does not explicitly differentiate itself from siblings like product_lifecycle, so it earns a 4 rather than a 5.

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?

The description provides no explicit guidance on when to use this tool versus the sibling tools check_project or product_lifecycle. There is no stated 'use this when...' or 'instead of...' condition; the only implicit signal is the batch-oriented wording 'up to 50', which is weaker than a clear routing instruction.

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

product_lifecycleA product's release cyclesB
Read-onlyIdempotent

Every maintained release cycle of a product (and the most recent ended ones) with status, release, end-of-active-support and end-of-life dates, LTS flag and latest patch, plus the recommended upgrade target.

ParametersJSON Schema
NameRequiredDescriptionDefault
productYes
include_endedNoHow many ended cycles to include; default 3

Output Schema

ParametersJSON Schema
NameRequiredDescription
cyclesYes
productYes

TDQS

B3.4/5.0
Behavior3/5

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

The annotations already cover safety (readOnly, idempotent, non-destructive), and the description adds useful scoping details: only maintained cycles plus recent ended ones are included, and the recommended upgrade target is provided. Nothing contradicts the annotations, but the behavioral context is modest.

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?

One dense, front-loaded sentence covers the resource and all key output aspects without filler. Every clause adds information, and the most important constraint ('maintained release cycle') comes first.

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 output schema and safety annotations, the description covers the return content and basic scope sufficiently for an agent to call the tool. The main missing element is explicit usage or alternative-selection guidance, but that is not essential for correct invocation.

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

Parameters3/5

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

Schema coverage is only 50%: include_ended has a description, but product is documented only as a string. The description identifies product as the lifecycle subject and hints at include_ended via 'most recent ended ones', adding some meaning. However, it does not explain how to reference a product or the interaction between the two parameters.

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 is specific and clear: it names the resource (a product's release cycles) and enumerates the returned fields (status, release, support/EOL dates, LTS flag, latest patch, upgrade target). It does not explicitly contrast itself with check_project or check_versions, so it misses the top score for sibling differentiation.

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?

There is no guidance about when to use this tool versus check_project or check_versions, nor any context about expected use cases or exclusions. The description only states what is returned, not how to choose it among siblings.

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. 3 tool updatesv0.1.0
    • First observedcheck_project
    • First observedcheck_versions
    • First observedproduct_lifecycle

TDQS

A3.7/5.0

Scored across 3 tools

Disambiguation4/5

check_project and check_versions both return EOL status for versions, but their inputs are clearly different (project files vs. explicit version pairs), so ambiguity is low. product_lifecycle is distinct, providing product-level release cycle information rather than checking specific versions. The slight overlap between checking a project's versions and checking explicit versions is resolvable from the descriptions.

Naming Consistency3/5

Two tools follow a verb_noun pattern (check_project, check_versions) with the same verb 'check', but product_lifecycle is a noun phrase without a verb, breaking the pattern. This is a minor inconsistency, and the names are still readable and intuitive, but a more consistent convention (e.g., get_product_lifecycle) would improve coherence.

Tool Count5/5

With 3 tools, the server is well-scoped for its purpose. Each tool covers a distinct need: scanning project files, checking explicit versions, and retrieving product lifecycle details. There is no redundancy or scope creep, and the count sits comfortably within the ideal 3-15 range.

Completeness5/5

The tool set covers the core end-of-life checking workflows: scanning project files, checking arbitrary version strings, and exploring a product's release lifecycle. This addresses the primary use cases without obvious dead ends. The only minor gap might be a dedicated single-version lookup, but check_versions handles that trivially by passing one version, so coverage feels complete.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to check software end-of-life dates and support status using the endoflife.date API, providing accurate information on software lifecycle, security status, and upgrade recommendations in real-time.
    5
    8
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Provides intelligent CSS/JS feature compatibility checking with configurable browser targets, polyfill support, and smart project scanning. Enables developers to automatically detect browser compatibility issues and get actionable remediation steps with build tool configurations.
    5
    3 npm
    3
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables inspection and analysis of project structures to detect languages, frameworks, entry points, and dependencies across multiple programming languages including Node.js, Python, PHP, Go, Java, and Rust.
    3
    5 npm
    1
    ISC
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables users to look up package versions, scan for vulnerabilities, and analyze dependencies across multiple registries (npm, Maven, PyPI, etc.) using exact version recommendations for security.
    4
    MIT