eladkishon

schengen-calculator

Community eladkishon
Updated

Schengen 90/180 and per-entry visa day calculator, plus a zero-dependency MCP server (npx -y github:eladkishon/schengen-calculator). TypeScript, gets the edge cases right.

schengen-calculator

Rolling-window (Schengen 90/180) and per-entry visa day counting. Zero dependencies, TypeScript,works in the browser and on the server.

npm i schengen-calculator
import { countDays, SCHENGEN } from "schengen-calculator";

const result = countDays(
  [
    { start: new Date("2026-01-05"), end: new Date("2026-01-20"), code: "FR" },
    { start: new Date("2026-03-01"), end: new Date("2026-03-14"), code: "IT" },
  ],
  SCHENGEN,
);

result.used;        // 30
result.remaining;   // 60
result.mustLeaveBy; // the date you have to be out by
result.entries;     // continuous presences, after merging

Use it from an AI agent (MCP)

The package is also an MCP server. Add it to Claude Desktop, Claude Code, Cursor or any MCP client:

{
  "mcpServers": {
    "schengen": { "command": "npx", "args": ["-y", "github:eladkishon/schengen-calculator"] }
  }
}

Tools:

  • calculate_schengen_days counts days used and left under the 90/180 rule. Runs locally.
  • check_visa_requirement returns the entry type and allowed stay for a passport and destination.
  • create_trip_plan saves a planned itinerary and returns a link the traveller opens to keep it in NomadPoint.

The last two call NomadPoint's public server, which needs no account or key. To skip the install,point a client that speaks Streamable HTTP straight athttps://gxhdcvoveufbkthhendf.supabase.co/functions/v1/mcp-public (registry name app.nomadpoint/travel-facts).

Why this exists

Counting days sounds like subtraction and isn't. These are the cases a home-made calculator getswrong, each of which is a real conversation with a border officer:

Entry and exit days both count. The 1st to the 10th is ten days, not nine. This singleoff-by-one is the most common bug in Schengen calculators.

Two records of one trip is still one trip. A flight arrival and a hotel booking describing thesame stay must not bill you twice. The rolling window counts unique days.

Moving inside the zone is one stay. Paris to Berlin does not start a new entry and does notdouble-count the day you travelled.

The gap between trips is not presence. If you fly home for February, February is not Schengentime. A counter that carries your last known country forward will invent weeks you never spent.

A per-entry allowance resets; a rolling one does not. US VWP gives you 90 days each entry.Schengen gives you 90 in any rolling 180 in total. Summing every past visit is wrong for thefirst; counting only the current visit is wrong for the second.

An arrival with no departure needs a bound. If all you know is that someone entered, presenceruns to the next position change — capped at one full allowance. Without the cap, one forgottenarrival implies years of continuous presence.

Days are UTC. Local midnight would make the answer depend on the machine's timezone.

API

countDays(spans, allowance, asOf?) → DayCount | null

spans are periods of presence. end: null means "arrived, no known departure".

interface PresenceSpan { start: Date; end: Date | null; code: string }  // ISO 3166-1 alpha-2

null is returned when there is nothing to count — no presence in the zone inside the window.

presenceIntervals(spans, zone, asOf, maxOpenStayDays?)

The merged continuous presences, if you want them without the counting.

Built-in allowances

SCHENGEN — 29 states, 90 days in any rolling 180.CA4 — Guatemala, El Salvador, Honduras, Nicaragua: 90 days pooled, per entry.

Anything else is a literal:

const US_VWP = { zone: ["US"], allowed: 90 };                          // per entry
const B1B2   = { zone: ["US"], allowed: 180 };                         // per entry

Accuracy

This is arithmetic over dates you supply, not immigration advice. It does not know your visa, yourresidence permit, exemptions, or the officer's discretion. Rules change. Check with the authoritythat issues the stamp.

Where it came from

Extracted from NomadPoint, a trip planner that tracks entry rules forevery traveller on a trip, across 39,601 passport-and-destination combinations. The counting engineis the same one running in the app; publishing it seemed more useful than everyone rewriting theoff-by-one.

MIT.

MCP Server · Populars

MCP Server · New

    fullselfbrowsing

    FSB v0.9.92 Full Self Browsing

    DOM-first AI browser automation for Chrome and MCP clients.

    Community fullselfbrowsing
    kody-hq

    kody

    🐨 Your agents' cloud — the memory, keys, code, and automations your AI agent keeps, portable across every MCP host.

    Community kody-hq
    rootSunc

    CNEquity · 中国市场金融数据湖

    中国 A 股数据基础设施。55个日更数据集:股票行情、基本面、期货数据、资金面、公告事件、指数行业、宏观与风险。行级溯源、PIT 语义、复权与历史成分内置,MCP 原生。自托管,零注册、零 API Token

    Community rootSunc
    VicPitic

    The Brains

    The smartest brains on earth, in an MCP. Cited, searchable MCP servers built from founders' talks, essays and posts.

    Community VicPitic
    metavert-io

    LightCMS

    Self-hosted CMS that works human or headless: full admin UI plus REST and MCP APIs, built-in semantic search and site chat, and content forking, versioning, diff/merge review, templates, approvals, and static page generation.

    Community metavert-io