Traveler.md Agent Plugin
An Agent Plugins v1.0.0 package that connects an agent to a traveler's own Traveler.md profile and Trip.md trip plans, and teaches it how to write them correctly.
Maintained by Traveler.md. Licensed under the MIT License.
What it gives an agent
Traveler.md is a travel memory the traveler owns rather than any one app: how they like to fly, where they like to stay, who they usually travel with. Trip.md is the plan for a single trip. Both live behind one MCP server, and both belong to the traveler, who authorizes access once and can revoke it at any time.
Install this package and an agent can:
- Recall a traveler's durable preferences instead of asking for them again every session.
- Record a new preference in the right place, so it survives into the next trip and the next agent.
- Create, find, update and archive trips, with the trip detail kept out of the durable profile.
- Recover correctly when a write collides with another agent writing the same section.
Eight tools cover it: read_profile, create_profile, update_profile, create_trip, read_trip, update_trip, list_trips and archive_trip.
Scope: travel memory only
This package connects your agent to a memory. The server stores and returns what the traveler has recorded. It has no inventory, no prices, no availability and no recommendation engine. It never returns a shortlist of hotels or a flight to book.
Your agent still does the recommending. Reading the profile changes what that recommendation is based on. "Where should we stay in Lisbon?" is still your agent's question to answer. After a read, it can answer with the neighborhood this traveler likes, the room they need, the budget they actually spend, and the fact that they are traveling with a toddler this year, so they never have to re-explain any of it.
An agent that treats the server as a booking tool fails in one of two ways. It waits for a shortlist that never arrives, or it skips the server on the question the profile was written to answer.
Install
The whole package
Agent Plugins v1 deliberately defines no install mechanism, distribution protocol, or registry. Each client owns its own install path, so follow your client's instructions for adding a local or Git-hosted Agent Plugin and point it at this repository. That path installs the skill as well as the server.
Codex and ChatGPT read Agent Plugins directly, and this repository doubles as a single-plugin marketplace, so they install it from the Git URL:
codex plugin marketplace add https://github.com/TravelAiSolution/traveler-md-agent-plugin
codex plugin add traveler-md@travelai
The first command registers the marketplace this repository declares, named travelai. The second installs the one plugin in it. The traveler is asked to authorize on first use rather than at install time.
The host reads the manifest at the repository root and finds the rest by convention: skills/ and mcp.json are already where it looks, so there is no second manifest to keep in step. The host cannot infer how the plugin appears in an install listing. That metadata lives under extensions["com.openai"] in plugin.json. See Portability across clients.
The MCP server on its own
If your client does not read Agent Plugins yet, connect the server directly. One click:
Add to Claude Add to Cursor Add to VS Code
Or one command:
claude mcp add --transport http travelermd https://mcp.traveler.md/mcp # Claude Code
codex mcp add travelermd --url https://mcp.traveler.md/mcp # Codex
Any other client that speaks remote MCP takes the URL directly:
{
"mcpServers": {
"travelermd": {
"url": "https://mcp.traveler.md/mcp"
}
}
}
This path gives the agent the tools without the skill. The next section explains what the skill adds. Per-client walkthroughs for Claude, Claude Code, Cursor, Codex, ChatGPT, Gemini and others are at https://docs.traveler.md/mcp.
There are no credentials to configure on either path. The package names the endpoint and nothing else: the traveler authorizes once through OAuth in their browser, and the client discovers the authorization server from the endpoint's protected-resource metadata.
Add this to your instruction file
Add a standing instruction so your agent reads the profile before it answers a travel question. Asked "where should we stay in Lisbon", a model usually answers from the conversation and leaves the profile unread.
If your client reads a project or global instruction file, paste this into it.
## Travel
Before recommending, shortlisting, planning or booking anything travel-related, read my
traveler.md profile with `read_profile`, and check `list_trips` for an existing trip
before starting a new one. Record lasting preferences with `update_profile` and
trip-specific detail with `update_trip`.
The file to put it in depends on the client: CLAUDE.md for Claude Code, AGENTS.md for Codex and others that follow that convention, a project rule for Cursor. Clients that read Agent Skills pick this up from the skill instead and need no manual step.
What is in the package
.
├── plugin.json # Portable manifest
├── mcp.json # One streamable-http server: mcp.traveler.md
├── skills/
│ ├── travelermd/ # The mechanics. Every other skill defers to this one
│ │ ├── SKILL.md # Read before you advise, the read-before-write loop, the five rules
│ │ └── references/
│ │ ├── tools.md # All 8 tools, exact argument and response shapes
│ │ ├── profile-sections.md # traveler.md sections, caps, profile-vs-trip
│ │ ├── trip-sections.md # trip.md sections, caps, status lifecycle
│ │ └── errors.md # Every error code and its recovery
│ │ # (each workflow skill below also carries
│ │ # agents/openai.yaml: display name, blurb,
│ │ # example prompt, declared MCP dependency)
│ ├── traveler-onboarding/ # Set up or deepen a profile, recover known trips
│ ├── add-trip/ # Assemble a trip from context and connected sources
│ ├── trip-interview/ # Fill a sparse trip, one adaptive question at a time
│ ├── trip-organizer/ # Deduplicate and re-file a messy trip
│ ├── trip-readiness-check/ # Pre-departure gaps, deadlines and unresolved items
│ └── post-trip-review/ # Debrief a finished trip, promote durable lessons
├── assets/ # Brand marks for the install listing
├── .agents/plugins/
│ └── marketplace.json # Makes this repo installable from its Git URL
└── scripts/ # Validation tooling, not part of the plugin
Agent Plugins v1 defines two portable component types, and this package ships both:
-
One MCP server.
https://mcp.traveler.md/mcp, Streamable HTTP. -
Seven skills.
travelermdis the mechanics: the server's tool schemas describe the arguments, and this skill covers the operational rules those schemas leave out. Writes replace a section wholesale, every update needs a version hash from a fresh read, and a misspelled argument name produces a successful-looking no-op.The other six are workflows, one per job a traveler actually asks for:
traveler-onboarding,add-trip,trip-interview,trip-organizer,trip-readiness-check,post-trip-review. Each covers when to ask a question rather than write, which record a fact belongs in, and where its own workflow can lose data. None of them restate a section name, a cap or a status; they defer totravelermdfor all of it, so there is one place to correct when the server moves.
scripts/ is not a plugin component. Agent Plugins v1 defines exactly two component types, skills
and MCP servers, and a client reads only plugin.json, skills/ and mcp.json. Everything else
here is repo tooling and is invisible to the clients that install this package. .agents/plugins/
is distribution. It tells a host where to find the plugin, and it is not installed with the plugin.
Why the skill ships alongside the server
Connecting the server takes one line of configuration. Using it correctly is harder. These mistakes are common:
- Writing without a fresh
expected_version_hash, then blind-retrying the same stale hash on the resulting conflict, which overwrites whatever the other writer put in those sections. - Sending only a new sentence for a section, which deletes everything else in it.
- Sending a section as
[], which erases it. The server refuses this without an explicitallow_clear_sections, and the skill says why the flag is not something to set pre-emptively. - Exceeding a per-section sentence cap.
- Writing trip specifics into the durable profile, which pollutes every later trip.
- Omitting
sectionson a create or profile update, which the published schema does not mark required but the server rejects anyway. - Reading an empty
list_tripspage that still carries anext_cursoras "no such trip", when it means "nothing on this page".
The skill documents each of these. It ships in the same package as the server config, so an agent has the rules before its first write.
Portability across clients
plugin.json's top-level schema is closed: only $schema, name, version, description, author, homepage, repository, license, keywords and extensions are permitted. Hooks, agents, commands and similar features are not portable v1 components. If a client needs them, they belong under a reverse-domain namespace that client owns, either as an extensions object in the manifest or as a top-level com.vendor.client/ directory.
This package uses exactly one such namespace, extensions["com.openai"], and only for how the plugin appears in an install listing: display name, category, listing copy, starter prompts, brand colour, the marks in assets/ and the links to the privacy policy and terms. None of it changes what the plugin does, every other conforming client ignores it, and no portable component is declared there.
The marks in assets/ are the Traveler.md logo and icon. The MIT licence covers the contents of this repository as a work, and it is not a licence to use TravelAI's names or logos.
That namespace is also why there is no .codex-plugin/plugin.json. An OpenAI host will read either one and prefers the extensions entry when both exist, so a second manifest would only restate name and version with nothing keeping the two in step.
Working on this repo
This package is content. There is no build step. Node 24 and pnpm are all you need, and .nvmrc
pins the version.
pnpm install
pnpm test # all three suites below, in order
pnpm validate # spec conformance
pnpm self-test # proves both checkers catch what they claim to
pnpm check-drift # skill vs the live MCP server
The lint and format commands, and what each one is for, are in CLAUDE.md.
| Suite | What it proves |
|---|---|
pnpm validate | plugin.json and mcp.json satisfy the published 1.0.0 schemas (both closed, so an unknown field fails), plus the semantic rules the schemas cannot express: cross-file version match, HTTPS and no-credentials-in-headers, skill discovery, Agent Skills frontmatter, working relative links, path containment. It also covers the rules an OpenAI host enforces on extensions["com.openai"] and on .agents/plugins/marketplace.json, taken from that host's implementation rather than its documentation, because the two diverge. |
pnpm self-test | The checkers reject what they claim to. Injects one deliberate fault at a time, against validate and check-drift both, and asserts each is caught by its intended check, so a fault cannot be masked by an unrelated failure. |
pnpm check-drift | The skill's section names, sentence caps, trip statuses, pagination limits and private-section flags still match what the MCP server advertises. |
The two Agent Plugins schemas are vendored under scripts/schemas/1.0.0/, fetched from their canonical URLs. Spec §10.1 forbids reassigning a published schema identifier to different contents, which is what makes vendoring safe. Clients are separately forbidden from fetching schemas at load time; validating in CI is fine.
Keeping the skill accurate
The skill states argument names, section names, caps, status values and error codes explicitly. Those statements make the skill useful. They also go stale when the server changes, so this package is updated in the same change as the server.
scripts/fixtures/live-surface.json is a pinned snapshot of the section caps, scopes and enums the
server advertises, generated by reading the server's own schema definitions rather than by hand.
check-drift compares the skill against it, so a claim that has drifted fails CI instead of quietly
misinforming an agent.
Regenerating that snapshot reads the Traveler.md server's schema definitions directly, so it is a
maintainer task and the command lives with the server rather than here. If you spot a claim in the
skill that the live server no longer honours, open an issue with what you observed and we will
refresh the fixture. A refresh that makes check-drift fail is the signal that the skill's prose
needs updating too, alongside the fixture.
Bump plugin.json version on any content change: clients use it for update checks and cache
freshness.
Two behaviours the skill documents are properties of the running server rather than of its published schemas, so they will not show up in a schema diff and the drift check cannot see them:
- Unknown top-level arguments are dropped rather than rejected, so a misspelled argument name
yields a successful-looking result that changed nothing. This is why the skill tells agents to
verify a write via
changes. Unknown section names insidesectionsare rejected normally. CONFLICTrecovery detail arrives in the error message rather than in a structured field, which is why the skill tells agents to read the message for the current hash.
Contributing
Issues and pull requests are welcome.
main is the release branch and develop is integration; open pull requests against develop.
Branch prefixes are feat/, fix/, chore/, ci/, docs/, refactor/, test/, and commit
subjects are conventional commits, lowercase.
Before opening a PR, run the three gates CI runs: pnpm format:check, pnpm lint:ci, pnpm test.
If your change touches anything the skill asserts about the MCP server, say in the PR what you
verified it against. A claim you cannot verify is better left out than guessed at, because an agent
will act on it against a real traveler's data.
License
MIT. Copyright (c) 2026 TravelAI Solutions Inc.
You are free to fork, adapt and redistribute this package. The licence covers the contents of this repository and grants no rights in the Traveler.md or TravelAI names, logos or other marks, so please do not present a fork in a way that implies Traveler.md published or endorsed it.